]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 30 Apr 2008 15:37:40 +0000 (08:37 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 30 Apr 2008 15:37:40 +0000 (08:37 -0700)
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc:
  [POWERPC] Fix crashkernel= handling when no crashkernel= specified
  [POWERPC] Make emergency stack safe for current_thread_info() use
  [POWERPC] spufs: add .gitignore for spu_save_dump.h & spu_restore_dump.h
  [POWERPC] spufs: trace spu_acquire_saved events
  [POWERPC] spufs: fix marker name for find_victim
  [POWERPC] spufs: add marker for destroy_spu_context
  [POWERPC] spufs: add sputrace marker parameter names
  [POWERPC] spufs: add context switch notification log
  [POWERPC] mpc5200: defconfigs for CM5200, Lite5200B, Motion-PRO and TQM5200
  [POWERPC] mpc5200: Switch mpc5200 dts files to dts-v1 format
  [POWERPC] mpc5200: Fix FEC error handling on FIFO errors
  [POWERPC] mpc5200: add Phytec pcm030 board support
  [POWERPC] mpc5200: add gpiolib support for mpc5200
  [POWERPC] mpc5200: add interrupt type function
  [POWERPC] mpc5200: Fix unterminated of_device_id table

1371 files changed:
Documentation/ABI/testing/sysfs-class-bdi [new file with mode: 0644]
Documentation/DMA-API.txt
Documentation/DMA-attributes.txt [new file with mode: 0644]
Documentation/DMA-mapping.txt
Documentation/DocBook/Makefile
Documentation/DocBook/debugobjects.tmpl [new file with mode: 0644]
Documentation/DocBook/rapidio.tmpl
Documentation/braille-console.txt [new file with mode: 0644]
Documentation/cgroups.txt
Documentation/controllers/devices.txt [new file with mode: 0644]
Documentation/controllers/resource_counter.txt [new file with mode: 0644]
Documentation/cpu-freq/user-guide.txt
Documentation/cpusets.txt
Documentation/feature-removal-schedule.txt
Documentation/filesystems/proc.txt
Documentation/i2c/writing-clients
Documentation/i386/boot.txt
Documentation/kernel-parameters.txt
Documentation/keys-request-key.txt
Documentation/keys.txt
Documentation/oops-tracing.txt
Documentation/sound/alsa/ALSA-Configuration.txt
Documentation/sysrq.txt
Documentation/video4linux/CARDLIST.saa7134
Documentation/video4linux/cx18.txt [new file with mode: 0644]
MAINTAINERS
arch/Kconfig
arch/alpha/kernel/asm-offsets.c
arch/alpha/kernel/pci.c
arch/arm/configs/am200epdkit_defconfig
arch/arm/kernel/asm-offsets.c
arch/arm/kernel/atags.c
arch/arm/kernel/ecard.c
arch/arm/kernel/kprobes-decode.c
arch/arm/kernel/kprobes.c
arch/arm/mach-at91/at91cap9_devices.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/board-csb337.c
arch/arm/mach-at91/board-dk.c
arch/arm/mach-at91/board-eb9200.c
arch/arm/mach-at91/pm.c
arch/arm/mach-davinci/clock.c
arch/arm/mach-iop32x/em7210.c
arch/arm/mach-iop32x/glantank.c
arch/arm/mach-iop32x/n2100.c
arch/arm/mach-ixp4xx/dsmg600-setup.c
arch/arm/mach-ixp4xx/nas100d-setup.c
arch/arm/mach-ixp4xx/nslu2-setup.c
arch/arm/mach-omap1/board-h2.c
arch/arm/mach-omap1/board-h3.c
arch/arm/mach-omap1/board-osk.c
arch/arm/mach-orion5x/addr-map.c
arch/arm/mach-orion5x/common.c
arch/arm/mach-orion5x/common.h
arch/arm/mach-orion5x/db88f5281-setup.c
arch/arm/mach-orion5x/dns323-setup.c
arch/arm/mach-orion5x/kurobox_pro-setup.c
arch/arm/mach-orion5x/pci.c
arch/arm/mach-orion5x/rd88f5182-setup.c
arch/arm/mach-orion5x/ts209-setup.c
arch/arm/mach-pxa/Makefile
arch/arm/mach-pxa/generic.c
arch/arm/mach-pxa/gumstix.c
arch/arm/mach-pxa/littleton.c
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-pxa/magician.c
arch/arm/mach-pxa/mainstone.c
arch/arm/mach-pxa/pcm990-baseboard.c
arch/arm/mach-pxa/pm.c
arch/arm/mach-pxa/pxa3xx.c
arch/arm/mach-pxa/zylonite.c
arch/arm/mm/Kconfig
arch/arm/mm/Makefile
arch/arm/mm/copypage-feroceon.S [new file with mode: 0644]
arch/arm/mm/iomap.c
arch/arm/mm/mmu.c
arch/arm/mm/proc-feroceon.S
arch/arm/oprofile/op_model_mpcore.c
arch/avr32/kernel/asm-offsets.c
arch/avr32/mm/tlb.c
arch/blackfin/kernel/asm-offsets.c
arch/blackfin/kernel/signal.c
arch/blackfin/mach-bf533/boards/stamp.c
arch/blackfin/mach-bf537/boards/stamp.c
arch/blackfin/mach-bf548/boards/ezkit.c
arch/cris/kernel/profile.c
arch/frv/kernel/asm-offsets.c
arch/frv/kernel/signal.c
arch/frv/kernel/traps.c
arch/frv/mb93090-mb00/pci-iomap.c
arch/frv/mm/unaligned.c [deleted file]
arch/h8300/kernel/asm-offsets.c
arch/ia64/Kconfig
arch/ia64/hp/common/hwsw_iommu.c
arch/ia64/hp/common/sba_iommu.c
arch/ia64/hp/sim/simserial.c
arch/ia64/kernel/asm-offsets.c
arch/ia64/kernel/perfmon.c
arch/ia64/kernel/process.c
arch/ia64/kernel/salinfo.c
arch/ia64/kernel/smpboot.c
arch/ia64/kernel/topology.c
arch/ia64/kernel/uncached.c
arch/ia64/mm/tlb.c
arch/ia64/sn/kernel/sn2/sn2_smp.c
arch/ia64/sn/kernel/sn2/sn_proc_fs.c
arch/ia64/sn/pci/pci_dma.c
arch/m68k/kernel/asm-offsets.c
arch/m68k/mac/iop.c
arch/m68k/mm/init.c
arch/m68knommu/kernel/asm-offsets.c
arch/mips/basler/excite/excite_procfs.c
arch/mips/kernel/asm-offsets.c
arch/mips/lib/iomap-pci.c
arch/mips/pmc-sierra/yosemite/setup.c
arch/mn10300/kernel/asm-offsets.c
arch/mn10300/unit-asb2305/pci-iomap.c
arch/parisc/kernel/asm-offsets.c
arch/parisc/kernel/pci-dma.c
arch/parisc/lib/iomap.c
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/lparcfg.c
arch/powerpc/kernel/ppc_ksyms.c
arch/powerpc/kernel/proc_ppc64.c
arch/powerpc/kernel/rtas-proc.c
arch/powerpc/kernel/rtas_flash.c
arch/powerpc/platforms/cell/spufs/sched.c
arch/powerpc/platforms/cell/spufs/sputrace.c
arch/powerpc/platforms/iseries/lpevents.c
arch/powerpc/platforms/iseries/mf.c
arch/powerpc/platforms/iseries/proc.c
arch/powerpc/platforms/iseries/viopath.c
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/reconfig.c
arch/powerpc/platforms/pseries/rtasd.c
arch/powerpc/sysdev/fsl_soc.c
arch/ppc/kernel/asm-offsets.c
arch/ppc/kernel/pci.c
arch/ppc/kernel/ppc_ksyms.c
arch/ppc/platforms/sbc82xx.c
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/entry.S
arch/s390/kernel/entry64.S
arch/s390/kernel/irq.c
arch/sh/boards/renesas/migor/setup.c
arch/sh/boards/renesas/r7780rp/setup.c
arch/sh/drivers/pci/pci.c
arch/sh/kernel/asm-offsets.c
arch/sh/kernel/irq.c
arch/sparc/kernel/asm-offsets.c
arch/sparc/kernel/sparc_ksyms.c
arch/sparc/lib/iomap.c
arch/sparc64/lib/iomap.c
arch/sparc64/mm/init.c
arch/um/kernel/exitcode.c
arch/um/kernel/process.c
arch/um/kernel/time.c
arch/v850/kernel/asm-offsets.c
arch/v850/kernel/rte_mb_a_pci.c
arch/x86/Kconfig
arch/x86/boot/edd.c
arch/x86/ia32/ia32_signal.c
arch/x86/kernel/Makefile
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/asm-offsets_32.c
arch/x86/kernel/asm-offsets_64.c
arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
arch/x86/kernel/cpu/mtrr/generic.c
arch/x86/kernel/cpu/mtrr/if.c
arch/x86/kernel/e820_64.c
arch/x86/kernel/irq_32.c
arch/x86/kernel/mmconf-fam10h_64.c [new file with mode: 0644]
arch/x86/kernel/olpc.c [new file with mode: 0644]
arch/x86/kernel/setup_64.c
arch/x86/kernel/signal_32.c
arch/x86/kernel/signal_64.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/time_32.c
arch/x86/kernel/vsmp_64.c
arch/x86/mm/k8topology_64.c
arch/x86/pci/Makefile_32
arch/x86/pci/Makefile_64
arch/x86/pci/acpi.c
arch/x86/pci/common.c
arch/x86/pci/direct.c
arch/x86/pci/fixup.c
arch/x86/pci/init.c
arch/x86/pci/irq.c
arch/x86/pci/k8-bus_64.c
arch/x86/pci/legacy.c
arch/x86/pci/mmconfig-shared.c
arch/x86/pci/mmconfig_32.c
arch/x86/pci/mmconfig_64.c
arch/x86/pci/mp_bus_to_node.c [new file with mode: 0644]
arch/x86/pci/olpc.c [new file with mode: 0644]
arch/x86/pci/pci.h
arch/xtensa/kernel/asm-offsets.c
block/blk-barrier.c
block/blk-core.c
block/blk-map.c
block/blk-merge.c
block/blk-settings.c
block/blk-sysfs.c
block/blk-tag.c
block/blk.h
block/elevator.c
block/genhd.c
block/scsi_ioctl.c
drivers/Kconfig
drivers/Makefile
drivers/accessibility/Kconfig [new file with mode: 0644]
drivers/accessibility/Makefile [new file with mode: 0644]
drivers/accessibility/braille/Makefile [new file with mode: 0644]
drivers/accessibility/braille/braille_console.c [new file with mode: 0644]
drivers/acpi/ac.c
drivers/acpi/battery.c
drivers/acpi/bus.c
drivers/acpi/button.c
drivers/acpi/ec.c
drivers/acpi/event.c
drivers/acpi/fan.c
drivers/acpi/power.c
drivers/acpi/processor_core.c
drivers/acpi/processor_idle.c
drivers/acpi/processor_perflib.c
drivers/acpi/processor_thermal.c
drivers/acpi/processor_throttling.c
drivers/acpi/sbs.c
drivers/acpi/sleep/proc.c
drivers/acpi/system.c
drivers/acpi/thermal.c
drivers/acpi/video.c
drivers/ata/Kconfig
drivers/ata/Makefile
drivers/ata/ahci.c
drivers/ata/libata-core.c
drivers/ata/libata-scsi.c
drivers/ata/libata.h
drivers/ata/pata_atiixp.c
drivers/ata/pata_bf54x.c
drivers/ata/pata_rb532_cf.c [moved from drivers/ata/pata_rb500_cf.c with 72% similarity]
drivers/ata/pata_via.c
drivers/ata/sata_mv.c
drivers/base/core.c
drivers/base/firmware_class.c
drivers/base/node.c
drivers/block/aoe/aoe.h
drivers/block/aoe/aoecmd.c
drivers/block/aoe/aoedev.c
drivers/block/aoe/aoenet.c
drivers/block/brd.c
drivers/block/cciss.c
drivers/block/cpqarray.c
drivers/block/floppy.c
drivers/block/loop.c
drivers/block/nbd.c
drivers/block/paride/pd.c
drivers/block/pktcdvd.c
drivers/block/ps3disk.c
drivers/block/ub.c
drivers/block/xen-blkfront.c
drivers/bluetooth/hci_ldisc.c
drivers/cdrom/cdrom.c
drivers/cdrom/viocd.c
drivers/char/Kconfig
drivers/char/agp/agp.h
drivers/char/amiserial.c
drivers/char/apm-emulation.c
drivers/char/applicom.c
drivers/char/consolemap.c
drivers/char/cyclades.c
drivers/char/drm/drmP.h
drivers/char/drm/drm_sysfs.c
drivers/char/drm/i830_dma.c
drivers/char/drm/i830_drv.h
drivers/char/drm/i830_irq.c
drivers/char/drm/i915_dma.c
drivers/char/drm/i915_drv.h
drivers/char/drm/radeon_cp.c
drivers/char/ds1286.c
drivers/char/epca.c
drivers/char/esp.c
drivers/char/generic_serial.c
drivers/char/hpet.c
drivers/char/hvsi.c
drivers/char/i8k.c
drivers/char/ip2/i2ellis.c
drivers/char/ip2/i2ellis.h
drivers/char/ip2/i2hw.h
drivers/char/ip2/i2lib.c
drivers/char/ip2/i2os.h [deleted file]
drivers/char/ip2/ip2main.c
drivers/char/ipmi/Makefile
drivers/char/ipmi/ipmi_bt_sm.c
drivers/char/ipmi/ipmi_kcs_sm.c
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/ipmi/ipmi_poweroff.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/ipmi/ipmi_si_sm.h
drivers/char/ipmi/ipmi_smic_sm.c
drivers/char/ipmi/ipmi_watchdog.c
drivers/char/isicom.c
drivers/char/istallion.c
drivers/char/keyboard.c
drivers/char/mem.c
drivers/char/misc.c
drivers/char/mmtimer.c
drivers/char/moxa.c
drivers/char/moxa.h [new file with mode: 0644]
drivers/char/mspec.c
drivers/char/mxser.c
drivers/char/mxser.h
drivers/char/n_hdlc.c
drivers/char/n_r3964.c
drivers/char/n_tty.c
drivers/char/nozomi.c
drivers/char/pcmcia/cm4000_cs.c
drivers/char/pcmcia/cm4040_cs.c
drivers/char/pcmcia/ipwireless/hardware.c
drivers/char/pcmcia/ipwireless/hardware.h
drivers/char/pcmcia/ipwireless/network.c
drivers/char/pcmcia/ipwireless/network.h
drivers/char/pcmcia/synclink_cs.c
drivers/char/pty.c
drivers/char/random.c
drivers/char/rio/cirrus.h
drivers/char/rio/rio_linux.c
drivers/char/rio/rio_linux.h
drivers/char/rio/riocmd.c
drivers/char/rio/rioctrl.c
drivers/char/rio/riointr.c
drivers/char/rio/rioparam.c
drivers/char/rio/riotty.c
drivers/char/riscom8.c
drivers/char/rocket.c
drivers/char/rocket_int.h
drivers/char/rtc.c
drivers/char/serial167.c
drivers/char/snsc.c
drivers/char/snsc_event.c
drivers/char/sonypi.c
drivers/char/specialix.c
drivers/char/stallion.c
drivers/char/sx.c
drivers/char/synclink.c
drivers/char/synclink_gt.c
drivers/char/synclinkmp.c
drivers/char/sysrq.c
drivers/char/toshiba.c
drivers/char/tpm/Kconfig
drivers/char/tpm/tpm_nsc.c
drivers/char/tty_audit.c
drivers/char/tty_io.c
drivers/char/tty_ioctl.c
drivers/char/viocons.c
drivers/char/viotape.c
drivers/char/vt.c
drivers/char/vt_ioctl.c
drivers/cpufreq/Kconfig
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_powersave.c
drivers/cpufreq/cpufreq_stats.c
drivers/edac/Kconfig
drivers/edac/amd76x_edac.c
drivers/edac/e752x_edac.c
drivers/edac/e7xxx_edac.c
drivers/edac/edac_device.c
drivers/edac/edac_mc.c
drivers/edac/edac_module.h
drivers/edac/edac_pci.c
drivers/edac/edac_pci_sysfs.c
drivers/edac/i3000_edac.c
drivers/edac/i5000_edac.c
drivers/edac/i82443bxgx_edac.c
drivers/edac/i82860_edac.c
drivers/edac/i82875p_edac.c
drivers/edac/i82975x_edac.c
drivers/edac/pasemi_edac.c
drivers/edac/r82600_edac.c
drivers/firmware/Kconfig
drivers/firmware/dcdbas.c
drivers/firmware/dell_rbu.c
drivers/gpio/gpiolib.c
drivers/gpio/pca953x.c
drivers/gpio/pcf857x.c
drivers/hid/hid-core.c
drivers/hwmon/ads7828.c
drivers/hwmon/f75375s.c
drivers/i2c/busses/i2c-amd756-s4882.c
drivers/i2c/busses/i2c-piix4.c
drivers/i2c/busses/i2c-sis5595.c
drivers/i2c/busses/i2c-sis630.c
drivers/i2c/busses/i2c-stub.c
drivers/i2c/busses/i2c-taos-evm.c
drivers/i2c/chips/ds1682.c
drivers/i2c/chips/menelaus.c
drivers/i2c/chips/tps65010.c
drivers/i2c/chips/tsl2550.c
drivers/i2c/i2c-core.c
drivers/ide/ide-cd.c
drivers/ide/ide-cd_verbose.c
drivers/ide/ide-io.c
drivers/ide/ide-proc.c
drivers/ide/ide-tape.c
drivers/ide/ide-taskfile.c
drivers/ide/ide.c
drivers/ide/pci/alim15x3.c
drivers/ide/pci/siimage.c
drivers/infiniband/core/umem.c
drivers/infiniband/hw/amso1100/c2_provider.c
drivers/infiniband/hw/cxgb3/cxio_hal.c
drivers/infiniband/hw/cxgb3/cxio_hal.h
drivers/infiniband/hw/cxgb3/cxio_wr.h
drivers/infiniband/hw/cxgb3/iwch.c
drivers/infiniband/hw/cxgb3/iwch.h
drivers/infiniband/hw/cxgb3/iwch_cm.c
drivers/infiniband/hw/cxgb3/iwch_cm.h
drivers/infiniband/hw/cxgb3/iwch_provider.c
drivers/infiniband/hw/cxgb3/iwch_provider.h
drivers/infiniband/hw/cxgb3/iwch_qp.c
drivers/infiniband/hw/ehca/ehca_classes.h
drivers/infiniband/hw/ehca/ehca_cq.c
drivers/infiniband/hw/ehca/ehca_eq.c
drivers/infiniband/hw/ehca/ehca_main.c
drivers/infiniband/hw/ehca/ehca_mrmw.c
drivers/infiniband/hw/ehca/ehca_qp.c
drivers/infiniband/hw/ipath/ipath_mr.c
drivers/infiniband/hw/mlx4/cq.c
drivers/infiniband/hw/mlx4/doorbell.c
drivers/infiniband/hw/mlx4/mr.c
drivers/infiniband/hw/mlx4/qp.c
drivers/infiniband/hw/mlx4/srq.c
drivers/infiniband/hw/mthca/mthca_mr.c
drivers/infiniband/hw/mthca/mthca_provider.c
drivers/infiniband/hw/mthca/mthca_provider.h
drivers/infiniband/hw/mthca/mthca_user.h
drivers/infiniband/hw/nes/Kconfig
drivers/infiniband/hw/nes/nes.c
drivers/infiniband/hw/nes/nes.h
drivers/infiniband/hw/nes/nes_cm.c
drivers/infiniband/hw/nes/nes_hw.c
drivers/infiniband/hw/nes/nes_hw.h
drivers/infiniband/hw/nes/nes_nic.c
drivers/infiniband/hw/nes/nes_utils.c
drivers/infiniband/hw/nes/nes_verbs.c
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_cm.c
drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_verbs.c
drivers/infiniband/ulp/ipoib/ipoib_vlan.c
drivers/infiniband/ulp/iser/iscsi_iser.c
drivers/infiniband/ulp/iser/iscsi_iser.h
drivers/infiniband/ulp/iser/iser_memory.c
drivers/input/input.c
drivers/input/serio/serport.c
drivers/input/tablet/aiptek.c
drivers/input/tablet/gtco.c
drivers/input/tablet/kbtab.c
drivers/isdn/capi/capi.c
drivers/isdn/capi/kcapi_proc.c
drivers/isdn/divert/divert_procfs.c
drivers/isdn/gigaset/ser-gigaset.c
drivers/isdn/hardware/eicon/divasproc.c
drivers/isdn/hysdn/hysdn_procconf.c
drivers/isdn/hysdn/hysdn_proclog.c
drivers/isdn/i4l/isdn_tty.c
drivers/leds/led-class.c
drivers/mca/mca-legacy.c
drivers/mca/mca-proc.c
drivers/md/dm-emc.c
drivers/md/dm-mpath-hp-sw.c
drivers/md/dm-mpath-rdac.c
drivers/md/dm-table.c
drivers/md/md.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/media/Kconfig
drivers/media/Makefile
drivers/media/common/Makefile
drivers/media/common/tuners/Kconfig [new file with mode: 0644]
drivers/media/common/tuners/Makefile [new file with mode: 0644]
drivers/media/common/tuners/mt2060.c [moved from drivers/media/dvb/frontends/mt2060.c with 100% similarity]
drivers/media/common/tuners/mt2060.h [moved from drivers/media/dvb/frontends/mt2060.h with 90% similarity]
drivers/media/common/tuners/mt2060_priv.h [moved from drivers/media/dvb/frontends/mt2060_priv.h with 100% similarity]
drivers/media/common/tuners/mt20xx.c [moved from drivers/media/video/mt20xx.c with 100% similarity]
drivers/media/common/tuners/mt20xx.h [moved from drivers/media/video/mt20xx.h with 91% similarity]
drivers/media/common/tuners/mt2131.c [moved from drivers/media/dvb/frontends/mt2131.c with 100% similarity]
drivers/media/common/tuners/mt2131.h [moved from drivers/media/dvb/frontends/mt2131.h with 91% similarity]
drivers/media/common/tuners/mt2131_priv.h [moved from drivers/media/dvb/frontends/mt2131_priv.h with 100% similarity]
drivers/media/common/tuners/mt2266.c [moved from drivers/media/dvb/frontends/mt2266.c with 100% similarity]
drivers/media/common/tuners/mt2266.h [moved from drivers/media/dvb/frontends/mt2266.h with 88% similarity]
drivers/media/common/tuners/qt1010.c [moved from drivers/media/dvb/frontends/qt1010.c with 100% similarity]
drivers/media/common/tuners/qt1010.h [moved from drivers/media/dvb/frontends/qt1010.h with 91% similarity]
drivers/media/common/tuners/qt1010_priv.h [moved from drivers/media/dvb/frontends/qt1010_priv.h with 100% similarity]
drivers/media/common/tuners/tda18271-common.c [moved from drivers/media/dvb/frontends/tda18271-common.c with 100% similarity]
drivers/media/common/tuners/tda18271-fe.c [moved from drivers/media/dvb/frontends/tda18271-fe.c with 100% similarity]
drivers/media/common/tuners/tda18271-maps.c [moved from drivers/media/dvb/frontends/tda18271-tables.c with 100% similarity]
drivers/media/common/tuners/tda18271-priv.h [moved from drivers/media/dvb/frontends/tda18271-priv.h with 100% similarity]
drivers/media/common/tuners/tda18271.h [moved from drivers/media/dvb/frontends/tda18271.h with 96% similarity]
drivers/media/common/tuners/tda827x.c [moved from drivers/media/dvb/frontends/tda827x.c with 100% similarity]
drivers/media/common/tuners/tda827x.h [moved from drivers/media/dvb/frontends/tda827x.h with 93% similarity]
drivers/media/common/tuners/tda8290.c [moved from drivers/media/video/tda8290.c with 99% similarity]
drivers/media/common/tuners/tda8290.h [moved from drivers/media/video/tda8290.h with 94% similarity]
drivers/media/common/tuners/tda9887.c [moved from drivers/media/video/tda9887.c with 100% similarity]
drivers/media/common/tuners/tda9887.h [moved from drivers/media/video/tda9887.h with 92% similarity]
drivers/media/common/tuners/tea5761.c [moved from drivers/media/video/tea5761.c with 100% similarity]
drivers/media/common/tuners/tea5761.h [moved from drivers/media/video/tea5761.h with 93% similarity]
drivers/media/common/tuners/tea5767.c [moved from drivers/media/video/tea5767.c with 100% similarity]
drivers/media/common/tuners/tea5767.h [moved from drivers/media/video/tea5767.h with 94% similarity]
drivers/media/common/tuners/tuner-i2c.h [moved from drivers/media/video/tuner-i2c.h with 100% similarity]
drivers/media/common/tuners/tuner-simple.c [moved from drivers/media/video/tuner-simple.c with 100% similarity]
drivers/media/common/tuners/tuner-simple.h [moved from drivers/media/video/tuner-simple.h with 92% similarity]
drivers/media/common/tuners/tuner-types.c [moved from drivers/media/video/tuner-types.c with 100% similarity]
drivers/media/common/tuners/tuner-xc2028-types.h [moved from drivers/media/video/tuner-xc2028-types.h with 100% similarity]
drivers/media/common/tuners/tuner-xc2028.c [moved from drivers/media/video/tuner-xc2028.c with 100% similarity]
drivers/media/common/tuners/tuner-xc2028.h [moved from drivers/media/video/tuner-xc2028.h with 93% similarity]
drivers/media/common/tuners/xc5000.c [moved from drivers/media/dvb/frontends/xc5000.c with 100% similarity]
drivers/media/common/tuners/xc5000.h [moved from drivers/media/dvb/frontends/xc5000.h with 92% similarity]
drivers/media/common/tuners/xc5000_priv.h [moved from drivers/media/dvb/frontends/xc5000_priv.h with 100% similarity]
drivers/media/dvb/Kconfig
drivers/media/dvb/b2c2/Kconfig
drivers/media/dvb/b2c2/Makefile
drivers/media/dvb/bt8xx/Kconfig
drivers/media/dvb/bt8xx/Makefile
drivers/media/dvb/bt8xx/dst.c
drivers/media/dvb/dvb-core/Kconfig [deleted file]
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvbdev.h
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/dvb-usb/Makefile
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/Makefile
drivers/media/dvb/frontends/s5h1420.c
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/au0828/Kconfig
drivers/media/video/au0828/Makefile
drivers/media/video/bt8xx/Kconfig
drivers/media/video/bt8xx/Makefile
drivers/media/video/bt8xx/bttvp.h
drivers/media/video/cs5345.c
drivers/media/video/cs53l32a.c
drivers/media/video/cx18/Kconfig [new file with mode: 0644]
drivers/media/video/cx18/Makefile [new file with mode: 0644]
drivers/media/video/cx18/cx18-audio.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-audio.h [new file with mode: 0644]
drivers/media/video/cx18/cx18-av-audio.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-av-core.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-av-core.h [new file with mode: 0644]
drivers/media/video/cx18/cx18-av-firmware.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-av-vbi.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-cards.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-cards.h [new file with mode: 0644]
drivers/media/video/cx18/cx18-controls.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-controls.h [new file with mode: 0644]
drivers/media/video/cx18/cx18-driver.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-driver.h [new file with mode: 0644]
drivers/media/video/cx18/cx18-dvb.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-dvb.h [new file with mode: 0644]
drivers/media/video/cx18/cx18-fileops.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-fileops.h [new file with mode: 0644]
drivers/media/video/cx18/cx18-firmware.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-firmware.h [new file with mode: 0644]
drivers/media/video/cx18/cx18-gpio.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-gpio.h [new file with mode: 0644]
drivers/media/video/cx18/cx18-i2c.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-i2c.h [new file with mode: 0644]
drivers/media/video/cx18/cx18-ioctl.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-ioctl.h [new file with mode: 0644]
drivers/media/video/cx18/cx18-irq.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-irq.h [new file with mode: 0644]
drivers/media/video/cx18/cx18-mailbox.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-mailbox.h [new file with mode: 0644]
drivers/media/video/cx18/cx18-queue.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-queue.h [new file with mode: 0644]
drivers/media/video/cx18/cx18-scb.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-scb.h [new file with mode: 0644]
drivers/media/video/cx18/cx18-streams.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-streams.h [new file with mode: 0644]
drivers/media/video/cx18/cx18-vbi.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-vbi.h [new file with mode: 0644]
drivers/media/video/cx18/cx18-version.h [new file with mode: 0644]
drivers/media/video/cx18/cx18-video.c [new file with mode: 0644]
drivers/media/video/cx18/cx18-video.h [new file with mode: 0644]
drivers/media/video/cx18/cx23418.h [new file with mode: 0644]
drivers/media/video/cx23885/Kconfig
drivers/media/video/cx23885/Makefile
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/cx88/Kconfig
drivers/media/video/cx88/Makefile
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-i2c.c
drivers/media/video/em28xx/Kconfig
drivers/media/video/em28xx/Makefile
drivers/media/video/ivtv/Kconfig
drivers/media/video/ivtv/Makefile
drivers/media/video/ivtv/ivtv-cards.c
drivers/media/video/ivtv/ivtv-cards.h
drivers/media/video/ivtv/ivtv-driver.c
drivers/media/video/ivtv/ivtv-fileops.c
drivers/media/video/ivtv/ivtv-gpio.c
drivers/media/video/ivtv/ivtv-i2c.c
drivers/media/video/ivtv/ivtv-ioctl.c
drivers/media/video/ivtv/ivtv-irq.c
drivers/media/video/ivtv/ivtv-version.h
drivers/media/video/ivtv/ivtvfb.c
drivers/media/video/m52790.c
drivers/media/video/msp3400-driver.c
drivers/media/video/mt9m001.c
drivers/media/video/mt9v022.c
drivers/media/video/pvrusb2/Kconfig
drivers/media/video/pvrusb2/Makefile
drivers/media/video/pvrusb2/pvrusb2-debug.h
drivers/media/video/pvrusb2/pvrusb2-devattr.c
drivers/media/video/pvrusb2/pvrusb2-dvb.c
drivers/media/video/saa7115.c
drivers/media/video/saa7127.c
drivers/media/video/saa7134/Kconfig
drivers/media/video/saa7134/Makefile
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7134/saa7134-i2c.c
drivers/media/video/saa7134/saa7134-input.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/saa717x.c
drivers/media/video/tcm825x.c
drivers/media/video/tlv320aic23b.c
drivers/media/video/tuner-core.c
drivers/media/video/tvaudio.c
drivers/media/video/upd64031a.c
drivers/media/video/upd64083.c
drivers/media/video/usbvideo/vicam.c
drivers/media/video/usbvision/Kconfig
drivers/media/video/usbvision/Makefile
drivers/media/video/v4l2-common.c
drivers/media/video/vp27smpx.c
drivers/media/video/wm8739.c
drivers/media/video/wm8775.c
drivers/media/video/zoran_procfs.c
drivers/message/i2o/i2o_block.c
drivers/message/i2o/i2o_proc.c
drivers/mfd/asic3.c
drivers/mfd/htc-pasic3.c
drivers/mfd/sm501.c
drivers/misc/hdpuftrs/hdpu_cpustate.c
drivers/misc/hdpuftrs/hdpu_nexus.c
drivers/misc/ibmasm/command.c
drivers/misc/ibmasm/heartbeat.c
drivers/misc/intel_menlow.c
drivers/misc/ioc4.c
drivers/misc/phantom.c
drivers/misc/sgi-xp/xpc_partition.c
drivers/misc/sony-laptop.c
drivers/mmc/host/mmc_spi.c
drivers/mmc/host/mmci.c
drivers/net/arm/am79c961a.c
drivers/net/bonding/bond_main.c
drivers/net/cxgb3/version.h
drivers/net/e100.c
drivers/net/hamachi.c
drivers/net/hamradio/6pack.c
drivers/net/hamradio/mkiss.c
drivers/net/ibmveth.c
drivers/net/irda/irtty-sir.c
drivers/net/irda/mcs7780.c
drivers/net/irda/stir4200.c
drivers/net/irda/vlsi_ir.c
drivers/net/mlx4/cq.c
drivers/net/mlx4/mr.c
drivers/net/myri10ge/myri10ge.c
drivers/net/ppp_async.c
drivers/net/ppp_synctty.c
drivers/net/pppoe.c
drivers/net/pppol2tp.c
drivers/net/slip.c
drivers/net/tehuti.c
drivers/net/tg3.c
drivers/net/tulip/de4x5.c
drivers/net/tulip/de4x5.h
drivers/net/tulip/tulip.h
drivers/net/tulip/tulip_core.c
drivers/net/wan/pc300_tty.c
drivers/net/wan/x25_asy.c
drivers/net/wireless/airo.c
drivers/net/wireless/ath5k/base.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/b43legacy/main.c
drivers/net/wireless/iwlwifi/iwl-3945.c
drivers/net/wireless/libertas/scan.c
drivers/net/wireless/strip.c
drivers/net/wireless/zd1211rw/zd_usb.c
drivers/net/yellowfin.c
drivers/nubus/proc.c
drivers/parisc/ccio-dma.c
drivers/parisc/sba_iommu.c
drivers/parport/ieee1284.c
drivers/parport/parport_gsc.c
drivers/parport/parport_pc.c
drivers/pci/hotplug/pciehp.h
drivers/pci/hotplug/pciehp_core.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/hotplug/shpchp_core.c
drivers/pci/msi.c
drivers/pci/pci-driver.c
drivers/pci/pcie/Kconfig
drivers/pci/probe.c
drivers/pci/proc.c
drivers/pcmcia/cistpl.c
drivers/pcmcia/pcmcia_ioctl.c
drivers/pnp/isapnp/proc.c
drivers/pnp/pnpbios/proc.c
drivers/power/ds2760_battery.c
drivers/power/olpc_battery.c
drivers/power/power_supply_core.c
drivers/power/power_supply_leds.c
drivers/rtc/rtc-bfin.c
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-ds1374.c
drivers/rtc/rtc-isl1208.c
drivers/rtc/rtc-m41t80.c
drivers/rtc/rtc-pcf8563.c
drivers/rtc/rtc-proc.c
drivers/rtc/rtc-rs5c372.c
drivers/rtc/rtc-s35390a.c
drivers/rtc/rtc-x1205.c
drivers/s390/block/dasd_proc.c
drivers/s390/char/con3215.c
drivers/s390/char/sclp_tty.c
drivers/s390/char/sclp_vt220.c
drivers/s390/char/tape_proc.c
drivers/s390/char/tty3270.c
drivers/s390/cio/blacklist.c
drivers/s390/cio/qdio.c
drivers/sbus/char/cpwatchdog.c
drivers/sbus/char/uctrl.c
drivers/scsi/megaraid.c
drivers/scsi/scsi_debug.c
drivers/scsi/scsi_devinfo.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_proc.c
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_transport_sas.c
drivers/scsi/sd.c
drivers/scsi/sg.c
drivers/serial/68328serial.c
drivers/serial/68360serial.c
drivers/serial/8250_early.c
drivers/serial/Kconfig
drivers/serial/Makefile
drivers/serial/bfin_5xx.c
drivers/serial/bfin_sport_uart.c [new file with mode: 0644]
drivers/serial/bfin_sport_uart.h [new file with mode: 0644]
drivers/serial/cpm_uart/cpm_uart_core.c
drivers/serial/crisv10.c
drivers/serial/ioc3_serial.c
drivers/serial/ioc4_serial.c
drivers/serial/kgdboc.c
drivers/serial/mcfserial.c
drivers/serial/netx-serial.c
drivers/serial/s3c2410.c
drivers/serial/sa1100.c
drivers/serial/serial_core.c
drivers/serial/sh-sci.c
drivers/serial/sn_console.c
drivers/serial/uartlite.c
drivers/serial/ucc_uart.c
drivers/spi/atmel_spi.c
drivers/usb/atm/ueagle-atm.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/inode.c
drivers/usb/gadget/at91_udc.c
drivers/usb/gadget/goku_udc.c
drivers/usb/gadget/omap_udc.c
drivers/usb/gadget/rndis.c
drivers/usb/gadget/serial.c
drivers/usb/gadget/usbstring.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ohci-hub.c
drivers/usb/host/sl811-hcd.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/usb-serial.c
drivers/usb/serial/whiteheat.c
drivers/video/Kconfig
drivers/video/clps711xfb.c
drivers/video/console/fbcon.c
drivers/video/console/mdacon.c
drivers/video/console/sticon.c
drivers/video/console/vgacon.c
drivers/video/matrox/matroxfb_misc.c
drivers/video/metronomefb.c
drivers/video/pxafb.c
drivers/video/pxafb.h
drivers/w1/w1_log.h
drivers/zorro/proc.c
fs/Kconfig.binfmt
fs/adfs/adfs.h
fs/adfs/dir_f.c
fs/affs/file.c
fs/affs/super.c
fs/afs/afs_cm.h
fs/afs/cell.c
fs/afs/cmservice.c
fs/afs/dir.c
fs/afs/internal.h
fs/afs/proc.c
fs/aio.c
fs/autofs4/autofs_i.h
fs/autofs4/root.c
fs/befs/linuxvfs.c
fs/bfs/bfs.h
fs/binfmt_aout.c
fs/binfmt_elf.c
fs/binfmt_elf_fdpic.c
fs/binfmt_em86.c
fs/binfmt_flat.c
fs/binfmt_misc.c
fs/binfmt_script.c
fs/bio.c
fs/buffer.c
fs/char_dev.c
fs/cifs/cifs_debug.c
fs/coda/coda_linux.c
fs/coda/dir.c
fs/compat.c
fs/compat_ioctl.c
fs/configfs/file.c
fs/configfs/inode.c
fs/configfs/mount.c
fs/configfs/symlink.c
fs/devpts/inode.c
fs/dlm/lockspace.c
fs/drop_caches.c
fs/ecryptfs/Makefile
fs/ecryptfs/crypto.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/file.c
fs/ecryptfs/inode.c
fs/ecryptfs/keystore.c
fs/ecryptfs/main.c
fs/ecryptfs/messaging.c
fs/ecryptfs/miscdev.c [new file with mode: 0644]
fs/ecryptfs/mmap.c
fs/ecryptfs/netlink.c
fs/ecryptfs/read_write.c
fs/eventpoll.c
fs/exec.c
fs/exportfs/expfs.c
fs/ext3/inode.c
fs/ext4/acl.c
fs/ext4/balloc.c
fs/ext4/bitmap.c
fs/ext4/dir.c
fs/ext4/ext4.h [moved from include/linux/ext4_fs.h with 99% similarity]
fs/ext4/ext4_extents.h [moved from include/linux/ext4_fs_extents.h with 98% similarity]
fs/ext4/ext4_i.h [moved from include/linux/ext4_fs_i.h with 97% similarity]
fs/ext4/ext4_jbd2.c
fs/ext4/ext4_jbd2.h [moved from include/linux/ext4_jbd2.h with 98% similarity]
fs/ext4/ext4_sb.h [moved from include/linux/ext4_fs_sb.h with 97% similarity]
fs/ext4/extents.c
fs/ext4/file.c
fs/ext4/fsync.c
fs/ext4/hash.c
fs/ext4/ialloc.c
fs/ext4/inode.c
fs/ext4/ioctl.c
fs/ext4/mballoc.c
fs/ext4/mballoc.h [new file with mode: 0644]
fs/ext4/migrate.c
fs/ext4/namei.c
fs/ext4/resize.c
fs/ext4/super.c
fs/ext4/symlink.c
fs/ext4/xattr.c
fs/ext4/xattr.h
fs/ext4/xattr_security.c
fs/ext4/xattr_trusted.c
fs/ext4/xattr_user.c
fs/fat/cache.c
fs/fat/fatent.c
fs/fat/file.c
fs/fat/inode.c
fs/freevxfs/vxfs_extern.h
fs/freevxfs/vxfs_immed.c
fs/freevxfs/vxfs_inode.c
fs/fs-writeback.c
fs/fuse/control.c
fs/fuse/dev.c
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
fs/gfs2/locking/dlm/sysfs.c
fs/gfs2/util.h
fs/hfs/btree.c
fs/hfs/mdb.c
fs/hfs/super.c
fs/hfsplus/btree.c
fs/hfsplus/hfsplus_fs.h
fs/hfsplus/inode.c
fs/hfsplus/options.c
fs/hfsplus/super.c
fs/hfsplus/wrapper.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/inotify_user.c
fs/ioctl.c
fs/isofs/dir.c
fs/isofs/isofs.h
fs/isofs/namei.c
fs/jbd2/commit.c
fs/jbd2/journal.c
fs/jbd2/revoke.c
fs/jbd2/transaction.c
fs/jffs2/debug.h
fs/jffs2/xattr.c
fs/jfs/jfs_debug.c
fs/lockd/clntproc.c
fs/lockd/svclock.c
fs/msdos/namei.c
fs/namei.c
fs/namespace.c
fs/ncpfs/ncplib_kernel.c
fs/nfs/client.c
fs/nfs/super.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfsctl.c
fs/ntfs/debug.h
fs/ntfs/mft.c
fs/ocfs2/dlm/dlmfs.c
fs/partitions/ldm.c
fs/proc/array.c
fs/proc/base.c
fs/proc/generic.c
fs/proc/inode.c
fs/proc/internal.h
fs/proc/nommu.c
fs/proc/proc_misc.c
fs/proc/proc_sysctl.c
fs/proc/proc_tty.c
fs/proc/root.c
fs/proc/task_mmu.c
fs/proc/task_nommu.c
fs/quota_v2.c
fs/ramfs/file-mmu.c
fs/ramfs/inode.c
fs/ramfs/internal.h
fs/reiserfs/journal.c
fs/reiserfs/procfs.c
fs/select.c
fs/smbfs/smb_debug.h
fs/splice.c
fs/super.c
fs/sync.c
fs/sysfs/file.c
fs/sysfs/inode.c
fs/sysfs/mount.c
fs/sysv/sysv.h
fs/timerfd.c
fs/udf/super.c
fs/vfat/namei.c
fs/xattr.c
fs/xfs/Kconfig
fs/xfs/linux-2.6/mrlock.h
fs/xfs/linux-2.6/xfs_buf.c
fs/xfs/linux-2.6/xfs_export.c
fs/xfs/linux-2.6/xfs_file.c
fs/xfs/linux-2.6/xfs_ioctl.c
fs/xfs/linux-2.6/xfs_iops.c
fs/xfs/linux-2.6/xfs_linux.h
fs/xfs/linux-2.6/xfs_lrw.c
fs/xfs/linux-2.6/xfs_lrw.h
fs/xfs/linux-2.6/xfs_super.c
fs/xfs/linux-2.6/xfs_vnode.h
fs/xfs/quota/xfs_dquot.c
fs/xfs/quota/xfs_qm.c
fs/xfs/quota/xfs_qm_syscalls.c
fs/xfs/quota/xfs_quota_priv.h
fs/xfs/quota/xfs_trans_dquot.c
fs/xfs/support/debug.h
fs/xfs/xfs.h
fs/xfs/xfs_acl.c
fs/xfs/xfs_attr.c
fs/xfs/xfs_attr.h
fs/xfs/xfs_bmap.c
fs/xfs/xfs_dfrag.c
fs/xfs/xfs_fsops.c
fs/xfs/xfs_ialloc.c
fs/xfs/xfs_iget.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_inode_item.c
fs/xfs/xfs_iomap.c
fs/xfs/xfs_itable.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_mount.h
fs/xfs/xfs_rename.c
fs/xfs/xfs_trans_inode.c
fs/xfs/xfs_utils.c
fs/xfs/xfs_utils.h
fs/xfs/xfs_vfsops.c
fs/xfs/xfs_vnodeops.c
fs/xfs/xfs_vnodeops.h
include/asm-alpha/unaligned.h
include/asm-arm/arch-orion5x/io.h
include/asm-arm/arch-pxa/irqs.h
include/asm-arm/arch-pxa/magician.h
include/asm-arm/arch-pxa/pxa-regs.h
include/asm-arm/arch-pxa/pxafb.h
include/asm-arm/arch-pxa/regs-lcd.h [new file with mode: 0644]
include/asm-arm/arch-pxa/system.h
include/asm-arm/page.h
include/asm-arm/unaligned.h
include/asm-avr32/unaligned.h
include/asm-blackfin/unaligned.h
include/asm-cris/unaligned.h
include/asm-frv/unaligned.h
include/asm-generic/bitops.h
include/asm-generic/futex.h
include/asm-generic/ioctl.h
include/asm-generic/memory_model.h
include/asm-generic/page.h
include/asm-generic/rtc.h
include/asm-generic/unaligned.h [deleted file]
include/asm-h8300/unaligned.h
include/asm-ia64/dma-mapping.h
include/asm-ia64/futex.h
include/asm-ia64/machvec.h
include/asm-ia64/machvec_hpzx1.h
include/asm-ia64/machvec_hpzx1_swiotlb.h
include/asm-ia64/machvec_sn2.h
include/asm-ia64/thread_info.h
include/asm-ia64/topology.h
include/asm-ia64/unaligned.h
include/asm-ia64/uncached.h
include/asm-m32r/unaligned.h
include/asm-m68k/unaligned.h
include/asm-m68knommu/unaligned.h
include/asm-mips/futex.h
include/asm-mips/unaligned.h
include/asm-mn10300/unaligned.h
include/asm-parisc/futex.h
include/asm-parisc/unaligned.h
include/asm-powerpc/futex.h
include/asm-powerpc/irq.h
include/asm-powerpc/unaligned.h
include/asm-s390/thread_info.h
include/asm-s390/unaligned.h
include/asm-sh/futex.h
include/asm-sh/unaligned.h
include/asm-sparc/unaligned.h
include/asm-sparc64/futex.h
include/asm-sparc64/unaligned.h
include/asm-um/unaligned.h
include/asm-v850/unaligned.h
include/asm-x86/futex.h
include/asm-x86/olpc.h [new file with mode: 0644]
include/asm-x86/pci.h
include/asm-x86/thread_info_32.h
include/asm-x86/thread_info_64.h
include/asm-x86/time.h
include/asm-x86/topology.h
include/asm-x86/tsc.h
include/asm-x86/unaligned.h
include/asm-xtensa/unaligned.h
include/linux/Kbuild
include/linux/acpi.h
include/linux/agp_backend.h
include/linux/aio.h
include/linux/audit.h
include/linux/backing-dev.h
include/linux/binfmts.h
include/linux/bio.h
include/linux/bitops.h
include/linux/blkdev.h
include/linux/buffer_head.h
include/linux/byteorder/Kbuild
include/linux/byteorder/big_endian.h
include/linux/byteorder/generic.h
include/linux/byteorder/little_endian.h
include/linux/capability.h
include/linux/cdev.h
include/linux/cgroup.h
include/linux/cgroup_subsys.h
include/linux/coda_fs_i.h
include/linux/coda_linux.h
include/linux/concap.h
include/linux/configfs.h
include/linux/console.h
include/linux/console_struct.h
include/linux/cpu.h
include/linux/cpufreq.h
include/linux/crc-ccitt.h
include/linux/dcache.h
include/linux/debugobjects.h [new file with mode: 0644]
include/linux/device-mapper.h
include/linux/device_cgroup.h [new file with mode: 0644]
include/linux/devpts_fs.h
include/linux/dma-attrs.h [new file with mode: 0644]
include/linux/dma-mapping.h
include/linux/edac.h
include/linux/elf.h
include/linux/eventfd.h
include/linux/fs.h
include/linux/fsl_devices.h
include/linux/fsnotify.h
include/linux/generic_serial.h
include/linux/gfp.h
include/linux/hrtimer.h
include/linux/hw_random.h
include/linux/i2c-id.h
include/linux/i2c.h
include/linux/i2o.h
include/linux/idr.h
include/linux/if_macvlan.h
include/linux/inet.h
include/linux/init.h
include/linux/interrupt.h
include/linux/ipc_namespace.h
include/linux/ipmi.h
include/linux/ipmi_smi.h
include/linux/isicom.h
include/linux/kbuild.h [new file with mode: 0644]
include/linux/kernel.h
include/linux/key.h
include/linux/keyctl.h
include/linux/kfifo.h
include/linux/kobj_map.h
include/linux/kobject.h
include/linux/kref.h
include/linux/libata.h
include/linux/list.h
include/linux/mca-legacy.h
include/linux/memcontrol.h
include/linux/memory.h
include/linux/mlx4/device.h
include/linux/mm.h
include/linux/mm_types.h
include/linux/mmzone.h
include/linux/mod_devicetable.h
include/linux/mount.h
include/linux/msg.h
include/linux/msi.h
include/linux/nbd.h
include/linux/ncp_fs_i.h
include/linux/netlink.h
include/linux/notifier.h
include/linux/of_device.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/percpu.h
include/linux/personality.h
include/linux/phantom.h
include/linux/pid.h
include/linux/pid_namespace.h
include/linux/pm.h
include/linux/pnp.h
include/linux/poison.h
include/linux/proc_fs.h
include/linux/profile.h
include/linux/proportions.h
include/linux/ptrace.h
include/linux/raid/md.h
include/linux/raid/md_k.h
include/linux/rcuclassic.h
include/linux/rcupdate.h
include/linux/rcupreempt.h
include/linux/rcupreempt_trace.h
include/linux/reiserfs_fs_sb.h
include/linux/res_counter.h
include/linux/resource.h
include/linux/rio.h
include/linux/rio_drv.h
include/linux/rwsem.h
include/linux/sched.h
include/linux/security.h
include/linux/seq_file.h
include/linux/serial_core.h
include/linux/signal.h
include/linux/slab.h
include/linux/smb.h
include/linux/smb_fs_i.h
include/linux/smb_fs_sb.h
include/linux/svga.h
include/linux/syscalls.h
include/linux/sysctl.h
include/linux/sysv_fs.h
include/linux/textsearch.h
include/linux/thread_info.h
include/linux/timer.h
include/linux/tty.h
include/linux/tty_driver.h
include/linux/unaligned/access_ok.h [new file with mode: 0644]
include/linux/unaligned/be_byteshift.h [new file with mode: 0644]
include/linux/unaligned/be_memmove.h [new file with mode: 0644]
include/linux/unaligned/be_struct.h [new file with mode: 0644]
include/linux/unaligned/generic.h [new file with mode: 0644]
include/linux/unaligned/le_byteshift.h [new file with mode: 0644]
include/linux/unaligned/le_memmove.h [new file with mode: 0644]
include/linux/unaligned/le_struct.h [new file with mode: 0644]
include/linux/unaligned/memmove.h [new file with mode: 0644]
include/linux/unaligned/packed_struct.h [new file with mode: 0644]
include/linux/writeback.h
include/linux/xattr.h
include/media/v4l2-chip-ident.h
include/media/v4l2-common.h
include/media/v4l2-i2c-drv-legacy.h
include/media/v4l2-i2c-drv.h
include/net/netlabel.h
include/net/xfrm.h
include/rdma/ib_umem.h
include/rdma/ib_verbs.h
include/scsi/libiscsi.h
include/sound/mpu401.h
init/Kconfig
init/initramfs.c
init/main.c
ipc/Makefile
ipc/ipc_sysctl.c
ipc/ipcns_notifier.c [new file with mode: 0644]
ipc/msg.c
ipc/namespace.c
ipc/sem.c
ipc/shm.c
ipc/util.c
ipc/util.h
kernel/Makefile
kernel/audit.c
kernel/audit.h
kernel/auditfilter.c
kernel/auditsc.c
kernel/bounds.c
kernel/cgroup.c
kernel/cgroup_debug.c
kernel/compat.c
kernel/configs.c
kernel/cpu.c
kernel/cpuset.c
kernel/dma.c
kernel/exit.c
kernel/fork.c
kernel/futex.c
kernel/hrtimer.c
kernel/irq/devres.c
kernel/irq/manage.c
kernel/kallsyms.c
kernel/kthread.c
kernel/latencytop.c
kernel/lockdep_proc.c
kernel/marker.c
kernel/notifier.c
kernel/ns_cgroup.c
kernel/nsproxy.c
kernel/panic.c
kernel/pid.c
kernel/pid_namespace.c
kernel/posix-timers.c
kernel/printk.c
kernel/profile.c
kernel/ptrace.c
kernel/rcutorture.c
kernel/relay.c
kernel/res_counter.c
kernel/resource.c
kernel/sched.c
kernel/sched_debug.c
kernel/signal.c
kernel/sys.c
kernel/sysctl.c
kernel/taskstats.c
kernel/time.c
kernel/time/timer_list.c
kernel/time/timer_stats.c
kernel/timer.c
kernel/user.c
kernel/user_namespace.c
kernel/utsname.c
kernel/workqueue.c
lib/Kconfig.debug
lib/Makefile
lib/debugobjects.c [new file with mode: 0644]
lib/find_next_bit.c
lib/idr.c
lib/inflate.c
lib/iomap.c
lib/kobject.c
lib/kobject_uevent.c
lib/percpu_counter.c
lib/proportions.c
lib/ratelimit.c [new file with mode: 0644]
lib/swiotlb.c
mm/backing-dev.c
mm/hugetlb.c
mm/memcontrol.c
mm/migrate.c
mm/mmap.c
mm/nommu.c
mm/page-writeback.c
mm/page_alloc.c
mm/readahead.c
mm/shmem.c
mm/slab.c
mm/slub.c
mm/sparse.c
mm/swap_state.c
mm/swapfile.c
mm/vmalloc.c
mm/vmscan.c
mm/vmstat.c
net/core/dev.c
net/ipv4/af_inet.c
net/irda/ircomm/ircomm_tty.c
net/irda/irnet/irnet_irda.c
net/irda/irnet/irnet_irda.h
net/key/af_key.c
net/netfilter/nf_queue.c
net/netlabel/netlabel_unlabeled.c
net/netlabel/netlabel_user.c
net/netlabel/netlabel_user.h
net/netlink/af_netlink.c
net/xfrm/xfrm_output.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
net/xfrm/xfrm_user.c
samples/markers/marker-example.c
scripts/Lindent
scripts/checkpatch.pl
scripts/kallsyms.c
scripts/mod/file2alias.c
security/Makefile
security/commoncap.c
security/device_cgroup.c [new file with mode: 0644]
security/dummy.c
security/keys/Makefile
security/keys/compat.c
security/keys/internal.h
security/keys/key.c
security/keys/keyctl.c
security/keys/keyring.c
security/keys/proc.c
security/keys/process_keys.c
security/keys/request_key.c
security/keys/request_key_auth.c
security/keys/sysctl.c [new file with mode: 0644]
security/security.c
security/selinux/avc.c
security/selinux/hooks.c
security/selinux/include/security.h
security/selinux/ss/services.c
security/smack/smack_lsm.c
security/smack/smackfs.c
sound/core/info.c
sound/core/memalloc.c
sound/drivers/Kconfig
sound/drivers/mpu401/mpu401_uart.c
sound/pci/hda/patch_realtek.c
sound/pci/ice1712/ice1724.c
sound/sh/aica.c
sound/soc/Kconfig
sound/soc/Makefile
sound/soc/codecs/wm9712.c
sound/soc/omap/Kconfig [new file with mode: 0644]
sound/soc/omap/Makefile [new file with mode: 0644]
sound/soc/omap/n810.c [new file with mode: 0644]
sound/soc/omap/omap-mcbsp.c [new file with mode: 0644]
sound/soc/omap/omap-mcbsp.h [new file with mode: 0644]
sound/soc/omap/omap-pcm.c [new file with mode: 0644]
sound/soc/omap/omap-pcm.h [new file with mode: 0644]

diff --git a/Documentation/ABI/testing/sysfs-class-bdi b/Documentation/ABI/testing/sysfs-class-bdi
new file mode 100644 (file)
index 0000000..5ac1e01
--- /dev/null
@@ -0,0 +1,46 @@
+What:          /sys/class/bdi/<bdi>/
+Date:          January 2008
+Contact:       Peter Zijlstra <a.p.zijlstra@chello.nl>
+Description:
+
+Provide a place in sysfs for the backing_dev_info object.  This allows
+setting and retrieving various BDI specific variables.
+
+The <bdi> identifier can be either of the following:
+
+MAJOR:MINOR
+
+       Device number for block devices, or value of st_dev on
+       non-block filesystems which provide their own BDI, such as NFS
+       and FUSE.
+
+default
+
+       The default backing dev, used for non-block device backed
+       filesystems which do not provide their own BDI.
+
+Files under /sys/class/bdi/<bdi>/
+---------------------------------
+
+read_ahead_kb (read-write)
+
+       Size of the read-ahead window in kilobytes
+
+min_ratio (read-write)
+
+       Under normal circumstances each device is given a part of the
+       total write-back cache that relates to its current average
+       writeout speed in relation to the other devices.
+
+       The 'min_ratio' parameter allows assigning a minimum
+       percentage of the write-back cache to a particular device.
+       For example, this is useful for providing a minimum QoS.
+
+max_ratio (read-write)
+
+       Allows limiting a particular device to use not more than the
+       given percentage of the write-back cache.  This is useful in
+       situations where we want to avoid one device taking all or
+       most of the write-back cache.  For example in case of an NFS
+       mount that is prone to get stuck, or a FUSE mount which cannot
+       be trusted to play fair.
index b939ebb62871ec6b743b02cd78be1ca6d230baae..80d150458c80c5ac7f7f5f75b3e6ff8a602a19ca 100644 (file)
@@ -145,7 +145,7 @@ Part Ic - DMA addressing limitations
 int
 dma_supported(struct device *dev, u64 mask)
 int
-pci_dma_supported(struct device *dev, u64 mask)
+pci_dma_supported(struct pci_dev *hwdev, u64 mask)
 
 Checks to see if the device can support DMA to the memory described by
 mask.
@@ -189,7 +189,7 @@ dma_addr_t
 dma_map_single(struct device *dev, void *cpu_addr, size_t size,
                      enum dma_data_direction direction)
 dma_addr_t
-pci_map_single(struct device *dev, void *cpu_addr, size_t size,
+pci_map_single(struct pci_dev *hwdev, void *cpu_addr, size_t size,
                      int direction)
 
 Maps a piece of processor virtual memory so it can be accessed by the
@@ -395,6 +395,71 @@ Notes:  You must do this:
 
 See also dma_map_single().
 
+dma_addr_t
+dma_map_single_attrs(struct device *dev, void *cpu_addr, size_t size,
+                    enum dma_data_direction dir,
+                    struct dma_attrs *attrs)
+
+void
+dma_unmap_single_attrs(struct device *dev, dma_addr_t dma_addr,
+                      size_t size, enum dma_data_direction dir,
+                      struct dma_attrs *attrs)
+
+int
+dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
+                int nents, enum dma_data_direction dir,
+                struct dma_attrs *attrs)
+
+void
+dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl,
+                  int nents, enum dma_data_direction dir,
+                  struct dma_attrs *attrs)
+
+The four functions above are just like the counterpart functions
+without the _attrs suffixes, except that they pass an optional
+struct dma_attrs*.
+
+struct dma_attrs encapsulates a set of "dma attributes". For the
+definition of struct dma_attrs see linux/dma-attrs.h.
+
+The interpretation of dma attributes is architecture-specific, and
+each attribute should be documented in Documentation/DMA-attributes.txt.
+
+If struct dma_attrs* is NULL, the semantics of each of these
+functions is identical to those of the corresponding function
+without the _attrs suffix. As a result dma_map_single_attrs()
+can generally replace dma_map_single(), etc.
+
+As an example of the use of the *_attrs functions, here's how
+you could pass an attribute DMA_ATTR_FOO when mapping memory
+for DMA:
+
+#include <linux/dma-attrs.h>
+/* DMA_ATTR_FOO should be defined in linux/dma-attrs.h and
+ * documented in Documentation/DMA-attributes.txt */
+...
+
+       DEFINE_DMA_ATTRS(attrs);
+       dma_set_attr(DMA_ATTR_FOO, &attrs);
+       ....
+       n = dma_map_sg_attrs(dev, sg, nents, DMA_TO_DEVICE, &attr);
+       ....
+
+Architectures that care about DMA_ATTR_FOO would check for its
+presence in their implementations of the mapping and unmapping
+routines, e.g.:
+
+void whizco_dma_map_sg_attrs(struct device *dev, dma_addr_t dma_addr,
+                            size_t size, enum dma_data_direction dir,
+                            struct dma_attrs *attrs)
+{
+       ....
+       int foo =  dma_get_attr(DMA_ATTR_FOO, attrs);
+       ....
+       if (foo)
+               /* twizzle the frobnozzle */
+       ....
+
 
 Part II - Advanced dma_ usage
 -----------------------------
diff --git a/Documentation/DMA-attributes.txt b/Documentation/DMA-attributes.txt
new file mode 100644 (file)
index 0000000..6d772f8
--- /dev/null
@@ -0,0 +1,24 @@
+                       DMA attributes
+                       ==============
+
+This document describes the semantics of the DMA attributes that are
+defined in linux/dma-attrs.h.
+
+DMA_ATTR_WRITE_BARRIER
+----------------------
+
+DMA_ATTR_WRITE_BARRIER is a (write) barrier attribute for DMA.  DMA
+to a memory region with the DMA_ATTR_WRITE_BARRIER attribute forces
+all pending DMA writes to complete, and thus provides a mechanism to
+strictly order DMA from a device across all intervening busses and
+bridges.  This barrier is not specific to a particular type of
+interconnect, it applies to the system as a whole, and so its
+implementation must account for the idiosyncracies of the system all
+the way from the DMA device to memory.
+
+As an example of a situation where DMA_ATTR_WRITE_BARRIER would be
+useful, suppose that a device does a DMA write to indicate that data is
+ready and available in memory.  The DMA of the "completion indication"
+could race with data DMA.  Mapping the memory used for completion
+indications with DMA_ATTR_WRITE_BARRIER would prevent the race.
+
index d84f89dbf921401ac0e7afbe2d291b4dc304ef97..b463ecd0c7cebf36f53104015afcbeeccf4b934d 100644 (file)
@@ -315,11 +315,11 @@ you should do:
 
        dma_addr_t dma_handle;
 
-       cpu_addr = pci_alloc_consistent(dev, size, &dma_handle);
+       cpu_addr = pci_alloc_consistent(pdev, size, &dma_handle);
 
-where dev is a struct pci_dev *. You should pass NULL for PCI like buses
-where devices don't have struct pci_dev (like ISA, EISA).  This may be
-called in interrupt context. 
+where pdev is a struct pci_dev *. This may be called in interrupt context.
+You should use dma_alloc_coherent (see DMA-API.txt) for buses
+where devices don't have struct pci_dev (like ISA, EISA).
 
 This argument is needed because the DMA translations may be bus
 specific (and often is private to the bus which the device is attached
@@ -332,7 +332,7 @@ __get_free_pages (but takes size instead of a page order).  If your
 driver needs regions sized smaller than a page, you may prefer using
 the pci_pool interface, described below.
 
-The consistent DMA mapping interfaces, for non-NULL dev, will by
+The consistent DMA mapping interfaces, for non-NULL pdev, will by
 default return a DMA address which is SAC (Single Address Cycle)
 addressable.  Even if the device indicates (via PCI dma mask) that it
 may address the upper 32-bits and thus perform DAC cycles, consistent
@@ -354,9 +354,9 @@ buffer you receive will not cross a 64K boundary.
 
 To unmap and free such a DMA region, you call:
 
-       pci_free_consistent(dev, size, cpu_addr, dma_handle);
+       pci_free_consistent(pdev, size, cpu_addr, dma_handle);
 
-where dev, size are the same as in the above call and cpu_addr and
+where pdev, size are the same as in the above call and cpu_addr and
 dma_handle are the values pci_alloc_consistent returned to you.
 This function may not be called in interrupt context.
 
@@ -371,9 +371,9 @@ Create a pci_pool like this:
 
        struct pci_pool *pool;
 
-       pool = pci_pool_create(name, dev, size, align, alloc);
+       pool = pci_pool_create(name, pdev, size, align, alloc);
 
-The "name" is for diagnostics (like a kmem_cache name); dev and size
+The "name" is for diagnostics (like a kmem_cache name); pdev and size
 are as above.  The device's hardware alignment requirement for this
 type of data is "align" (which is expressed in bytes, and must be a
 power of two).  If your device has no boundary crossing restrictions,
@@ -472,11 +472,11 @@ To map a single region, you do:
        void *addr = buffer->ptr;
        size_t size = buffer->len;
 
-       dma_handle = pci_map_single(dev, addr, size, direction);
+       dma_handle = pci_map_single(pdev, addr, size, direction);
 
 and to unmap it:
 
-       pci_unmap_single(dev, dma_handle, size, direction);
+       pci_unmap_single(pdev, dma_handle, size, direction);
 
 You should call pci_unmap_single when the DMA activity is finished, e.g.
 from the interrupt which told you that the DMA transfer is done.
@@ -493,17 +493,17 @@ Specifically:
        unsigned long offset = buffer->offset;
        size_t size = buffer->len;
 
-       dma_handle = pci_map_page(dev, page, offset, size, direction);
+       dma_handle = pci_map_page(pdev, page, offset, size, direction);
 
        ...
 
-       pci_unmap_page(dev, dma_handle, size, direction);
+       pci_unmap_page(pdev, dma_handle, size, direction);
 
 Here, "offset" means byte offset within the given page.
 
 With scatterlists, you map a region gathered from several regions by:
 
-       int i, count = pci_map_sg(dev, sglist, nents, direction);
+       int i, count = pci_map_sg(pdev, sglist, nents, direction);
        struct scatterlist *sg;
 
        for_each_sg(sglist, sg, count, i) {
@@ -527,7 +527,7 @@ accessed sg->address and sg->length as shown above.
 
 To unmap a scatterlist, just call:
 
-       pci_unmap_sg(dev, sglist, nents, direction);
+       pci_unmap_sg(pdev, sglist, nents, direction);
 
 Again, make sure DMA activity has already finished.
 
@@ -550,11 +550,11 @@ correct copy of the DMA buffer.
 So, firstly, just map it with pci_map_{single,sg}, and after each DMA
 transfer call either:
 
-       pci_dma_sync_single_for_cpu(dev, dma_handle, size, direction);
+       pci_dma_sync_single_for_cpu(pdev, dma_handle, size, direction);
 
 or:
 
-       pci_dma_sync_sg_for_cpu(dev, sglist, nents, direction);
+       pci_dma_sync_sg_for_cpu(pdev, sglist, nents, direction);
 
 as appropriate.
 
@@ -562,7 +562,7 @@ Then, if you wish to let the device get at the DMA area again,
 finish accessing the data with the cpu, and then before actually
 giving the buffer to the hardware call either:
 
-       pci_dma_sync_single_for_device(dev, dma_handle, size, direction);
+       pci_dma_sync_single_for_device(pdev, dma_handle, size, direction);
 
 or:
 
@@ -739,7 +739,7 @@ failure can be determined by:
 
        dma_addr_t dma_handle;
 
-       dma_handle = pci_map_single(dev, addr, size, direction);
+       dma_handle = pci_map_single(pdev, addr, size, direction);
        if (pci_dma_mapping_error(dma_handle)) {
                /*
                 * reduce current DMA mapping usage,
index 83966e94cc32308579b7b6f041c4299fad94fbd5..0eb0d027eb32e139f442eb30e3b92a7560112bed 100644 (file)
@@ -12,7 +12,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
            kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
            gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
            genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
-           mac80211.xml
+           mac80211.xml debugobjects.xml
 
 ###
 # The build process is as follows (targets):
diff --git a/Documentation/DocBook/debugobjects.tmpl b/Documentation/DocBook/debugobjects.tmpl
new file mode 100644 (file)
index 0000000..7f5f218
--- /dev/null
@@ -0,0 +1,391 @@
+<?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" []>
+
+<book id="debug-objects-guide">
+ <bookinfo>
+  <title>Debug objects life time</title>
+
+  <authorgroup>
+   <author>
+    <firstname>Thomas</firstname>
+    <surname>Gleixner</surname>
+    <affiliation>
+     <address>
+      <email>tglx@linutronix.de</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2008</year>
+   <holder>Thomas Gleixner</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>
+      debugobjects is a generic infrastructure to track the life time
+      of kernel objects and validate the operations on those.
+    </para>
+    <para>
+      debugobjects is useful to check for the following error patterns:
+       <itemizedlist>
+         <listitem><para>Activation of uninitialized objects</para></listitem>
+         <listitem><para>Initialization of active objects</para></listitem>
+         <listitem><para>Usage of freed/destroyed objects</para></listitem>
+       </itemizedlist>
+    </para>
+    <para>
+      debugobjects is not changing the data structure of the real
+      object so it can be compiled in with a minimal runtime impact
+      and enabled on demand with a kernel command line option.
+    </para>
+  </chapter>
+
+  <chapter id="howto">
+    <title>Howto use debugobjects</title>
+    <para>
+      A kernel subsystem needs to provide a data structure which
+      describes the object type and add calls into the debug code at
+      appropriate places. The data structure to describe the object
+      type needs at minimum the name of the object type. Optional
+      functions can and should be provided to fixup detected problems
+      so the kernel can continue to work and the debug information can
+      be retrieved from a live system instead of hard core debugging
+      with serial consoles and stack trace transcripts from the
+      monitor.
+    </para>
+    <para>
+      The debug calls provided by debugobjects are:
+      <itemizedlist>
+       <listitem><para>debug_object_init</para></listitem>
+       <listitem><para>debug_object_init_on_stack</para></listitem>
+       <listitem><para>debug_object_activate</para></listitem>
+       <listitem><para>debug_object_deactivate</para></listitem>
+       <listitem><para>debug_object_destroy</para></listitem>
+       <listitem><para>debug_object_free</para></listitem>
+      </itemizedlist>
+      Each of these functions takes the address of the real object and
+      a pointer to the object type specific debug description
+      structure.
+    </para>
+    <para>
+      Each detected error is reported in the statistics and a limited
+      number of errors are printk'ed including a full stack trace.
+    </para>
+    <para>
+      The statistics are available via debugfs/debug_objects/stats.
+      They provide information about the number of warnings and the
+      number of successful fixups along with information about the
+      usage of the internal tracking objects and the state of the
+      internal tracking objects pool.
+    </para>
+  </chapter>
+  <chapter id="debugfunctions">
+    <title>Debug functions</title>
+    <sect1 id="prototypes">
+      <title>Debug object function reference</title>
+!Elib/debugobjects.c
+    </sect1>
+    <sect1 id="debug_object_init">
+      <title>debug_object_init</title>
+      <para>
+       This function is called whenever the initialization function
+       of a real object is called.
+      </para>
+      <para>
+       When the real object is already tracked by debugobjects it is
+       checked, whether the object can be initialized.  Initializing
+       is not allowed for active and destroyed objects. When
+       debugobjects detects an error, then it calls the fixup_init
+       function of the object type description structure if provided
+       by the caller. The fixup function can correct the problem
+       before the real initialization of the object happens. E.g. it
+       can deactivate an active object in order to prevent damage to
+       the subsystem.
+      </para>
+      <para>
+       When the real object is not yet tracked by debugobjects,
+       debugobjects allocates a tracker object for the real object
+       and sets the tracker object state to ODEBUG_STATE_INIT. It
+       verifies that the object is not on the callers stack. If it is
+       on the callers stack then a limited number of warnings
+       including a full stack trace is printk'ed. The calling code
+       must use debug_object_init_on_stack() and remove the object
+       before leaving the function which allocated it. See next
+       section.
+      </para>
+    </sect1>
+
+    <sect1 id="debug_object_init_on_stack">
+      <title>debug_object_init_on_stack</title>
+      <para>
+       This function is called whenever the initialization function
+       of a real object which resides on the stack is called.
+      </para>
+      <para>
+       When the real object is already tracked by debugobjects it is
+       checked, whether the object can be initialized. Initializing
+       is not allowed for active and destroyed objects. When
+       debugobjects detects an error, then it calls the fixup_init
+       function of the object type description structure if provided
+       by the caller. The fixup function can correct the problem
+       before the real initialization of the object happens. E.g. it
+       can deactivate an active object in order to prevent damage to
+       the subsystem.
+      </para>
+      <para>
+       When the real object is not yet tracked by debugobjects
+       debugobjects allocates a tracker object for the real object
+       and sets the tracker object state to ODEBUG_STATE_INIT. It
+       verifies that the object is on the callers stack.
+      </para>
+      <para>
+       An object which is on the stack must be removed from the
+       tracker by calling debug_object_free() before the function
+       which allocates the object returns. Otherwise we keep track of
+       stale objects.
+      </para>
+    </sect1>
+
+    <sect1 id="debug_object_activate">
+      <title>debug_object_activate</title>
+      <para>
+       This function is called whenever the activation function of a
+       real object is called.
+      </para>
+      <para>
+       When the real object is already tracked by debugobjects it is
+       checked, whether the object can be activated.  Activating is
+       not allowed for active and destroyed objects. When
+       debugobjects detects an error, then it calls the
+       fixup_activate function of the object type description
+       structure if provided by the caller. The fixup function can
+       correct the problem before the real activation of the object
+       happens. E.g. it can deactivate an active object in order to
+       prevent damage to the subsystem.
+      </para>
+      <para>
+       When the real object is not yet tracked by debugobjects then
+       the fixup_activate function is called if available. This is
+       necessary to allow the legitimate activation of statically
+       allocated and initialized objects. The fixup function checks
+       whether the object is valid and calls the debug_objects_init()
+       function to initialize the tracking of this object.
+      </para>
+      <para>
+       When the activation is legitimate, then the state of the
+       associated tracker object is set to ODEBUG_STATE_ACTIVE.
+      </para>
+    </sect1>
+
+    <sect1 id="debug_object_deactivate">
+      <title>debug_object_deactivate</title>
+      <para>
+       This function is called whenever the deactivation function of
+       a real object is called.
+      </para>
+      <para>
+       When the real object is tracked by debugobjects it is checked,
+       whether the object can be deactivated. Deactivating is not
+       allowed for untracked or destroyed objects.
+      </para>
+      <para>
+       When the deactivation is legitimate, then the state of the
+       associated tracker object is set to ODEBUG_STATE_INACTIVE.
+      </para>
+    </sect1>
+
+    <sect1 id="debug_object_destroy">
+      <title>debug_object_destroy</title>
+      <para>
+       This function is called to mark an object destroyed. This is
+       useful to prevent the usage of invalid objects, which are
+       still available in memory: either statically allocated objects
+       or objects which are freed later.
+      </para>
+      <para>
+       When the real object is tracked by debugobjects it is checked,
+       whether the object can be destroyed. Destruction is not
+       allowed for active and destroyed objects. When debugobjects
+       detects an error, then it calls the fixup_destroy function of
+       the object type description structure if provided by the
+       caller. The fixup function can correct the problem before the
+       real destruction of the object happens. E.g. it can deactivate
+       an active object in order to prevent damage to the subsystem.
+      </para>
+      <para>
+       When the destruction is legitimate, then the state of the
+       associated tracker object is set to ODEBUG_STATE_DESTROYED.
+      </para>
+    </sect1>
+
+    <sect1 id="debug_object_free">
+      <title>debug_object_free</title>
+      <para>
+       This function is called before an object is freed.
+      </para>
+      <para>
+       When the real object is tracked by debugobjects it is checked,
+       whether the object can be freed. Free is not allowed for
+       active objects. When debugobjects detects an error, then it
+       calls the fixup_free function of the object type description
+       structure if provided by the caller. The fixup function can
+       correct the problem before the real free of the object
+       happens. E.g. it can deactivate an active object in order to
+       prevent damage to the subsystem.
+      </para>
+      <para>
+       Note that debug_object_free removes the object from the
+       tracker. Later usage of the object is detected by the other
+       debug checks.
+      </para>
+    </sect1>
+  </chapter>
+  <chapter id="fixupfunctions">
+    <title>Fixup functions</title>
+    <sect1 id="debug_obj_descr">
+      <title>Debug object type description structure</title>
+!Iinclude/linux/debugobjects.h
+    </sect1>
+    <sect1 id="fixup_init">
+      <title>fixup_init</title>
+      <para>
+       This function is called from the debug code whenever a problem
+       in debug_object_init is detected. The function takes the
+       address of the object and the state which is currently
+       recorded in the tracker.
+      </para>
+      <para>
+       Called from debug_object_init when the object state is:
+       <itemizedlist>
+         <listitem><para>ODEBUG_STATE_ACTIVE</para></listitem>
+       </itemizedlist>
+      </para>
+      <para>
+       The function returns 1 when the fixup was successful,
+       otherwise 0. The return value is used to update the
+       statistics.
+      </para>
+      <para>
+       Note, that the function needs to call the debug_object_init()
+       function again, after the damage has been repaired in order to
+       keep the state consistent.
+      </para>
+    </sect1>
+
+    <sect1 id="fixup_activate">
+      <title>fixup_activate</title>
+      <para>
+       This function is called from the debug code whenever a problem
+       in debug_object_activate is detected.
+      </para>
+      <para>
+       Called from debug_object_activate when the object state is:
+       <itemizedlist>
+         <listitem><para>ODEBUG_STATE_NOTAVAILABLE</para></listitem>
+         <listitem><para>ODEBUG_STATE_ACTIVE</para></listitem>
+       </itemizedlist>
+      </para>
+      <para>
+       The function returns 1 when the fixup was successful,
+       otherwise 0. The return value is used to update the
+       statistics.
+      </para>
+      <para>
+       Note that the function needs to call the debug_object_activate()
+       function again after the damage has been repaired in order to
+       keep the state consistent.
+      </para>
+      <para>
+       The activation of statically initialized objects is a special
+       case. When debug_object_activate() has no tracked object for
+       this object address then fixup_activate() is called with
+       object state ODEBUG_STATE_NOTAVAILABLE. The fixup function
+       needs to check whether this is a legitimate case of a
+       statically initialized object or not. In case it is it calls
+       debug_object_init() and debug_object_activate() to make the
+       object known to the tracker and marked active. In this case
+       the function should return 0 because this is not a real fixup.
+      </para>
+    </sect1>
+
+    <sect1 id="fixup_destroy">
+      <title>fixup_destroy</title>
+      <para>
+       This function is called from the debug code whenever a problem
+       in debug_object_destroy is detected.
+      </para>
+      <para>
+       Called from debug_object_destroy when the object state is:
+       <itemizedlist>
+         <listitem><para>ODEBUG_STATE_ACTIVE</para></listitem>
+       </itemizedlist>
+      </para>
+      <para>
+       The function returns 1 when the fixup was successful,
+       otherwise 0. The return value is used to update the
+       statistics.
+      </para>
+    </sect1>
+    <sect1 id="fixup_free">
+      <title>fixup_free</title>
+      <para>
+       This function is called from the debug code whenever a problem
+       in debug_object_free is detected. Further it can be called
+       from the debug checks in kfree/vfree, when an active object is
+       detected from the debug_check_no_obj_freed() sanity checks.
+      </para>
+      <para>
+       Called from debug_object_free() or debug_check_no_obj_freed()
+       when the object state is:
+       <itemizedlist>
+         <listitem><para>ODEBUG_STATE_ACTIVE</para></listitem>
+       </itemizedlist>
+      </para>
+      <para>
+       The function returns 1 when the fixup was successful,
+       otherwise 0. The return value is used to update the
+       statistics.
+      </para>
+    </sect1>
+  </chapter>
+  <chapter id="bugs">
+    <title>Known Bugs And Assumptions</title>
+    <para>
+       None (knock on wood).
+    </para>
+  </chapter>
+</book>
index b9e143e28c641ebec67d7e422b8ff81e97cda2a4..54eb26b573720e21a85a4181000b603de4678fcb 100644 (file)
 !Idrivers/rapidio/rio-sysfs.c
      </sect1>
      <sect1 id="PPC32_support"><title>PPC32 support</title>
-!Iarch/powerpc/kernel/rio.c
 !Earch/powerpc/sysdev/fsl_rio.c
 !Iarch/powerpc/sysdev/fsl_rio.c
      </sect1>
diff --git a/Documentation/braille-console.txt b/Documentation/braille-console.txt
new file mode 100644 (file)
index 0000000..000b0fb
--- /dev/null
@@ -0,0 +1,34 @@
+                       Linux Braille Console
+
+To get early boot messages on a braille device (before userspace screen
+readers can start), you first need to compile the support for the usual serial
+console (see serial-console.txt), and for braille device (in Device Drivers -
+Accessibility).
+
+Then you need to specify a console=brl, option on the kernel command line, the
+format is:
+
+       console=brl,serial_options...
+
+where serial_options... are the same as described in serial-console.txt
+
+So for instance you can use console=brl,ttyS0 if the braille device is connected
+to the first serial port, and console=brl,ttyS0,115200 to override the baud rate
+to 115200, etc.
+
+By default, the braille device will just show the last kernel message (console
+mode).  To review previous messages, press the Insert key to switch to the VT
+review mode.  In review mode, the arrow keys permit to browse in the VT content,
+page up/down keys go at the top/bottom of the screen, and the home key goes back
+to the cursor, hence providing very basic screen reviewing facility.
+
+Sound feedback can be obtained by adding the braille_console.sound=1 kernel
+parameter.
+
+For simplicity, only one braille console can be enabled, other uses of
+console=brl,... will be discarded.  Also note that it does not interfere with
+the console selection mecanism described in serial-console.txt
+
+For now, only the VisioBraille device is supported.
+
+Samuel Thibault <samuel.thibault@ens-lyon.org>
index 31d12e21ff8a9a780cbdeef130421d419338e310..c298a6690e0d67700b08b933a65a3eb4fd97cd96 100644 (file)
@@ -500,8 +500,7 @@ post-attachment activity that requires memory allocations or blocking.
 
 void fork(struct cgroup_subsy *ss, struct task_struct *task)
 
-Called when a task is forked into a cgroup. Also called during
-registration for all existing tasks.
+Called when a task is forked into a cgroup.
 
 void exit(struct cgroup_subsys *ss, struct task_struct *task)
 
diff --git a/Documentation/controllers/devices.txt b/Documentation/controllers/devices.txt
new file mode 100644 (file)
index 0000000..4dcea42
--- /dev/null
@@ -0,0 +1,48 @@
+Device Whitelist Controller
+
+1. Description:
+
+Implement a cgroup to track and enforce open and mknod restrictions
+on device files.  A device cgroup associates a device access
+whitelist with each cgroup.  A whitelist entry has 4 fields.
+'type' is a (all), c (char), or b (block).  'all' means it applies
+to all types and all major and minor numbers.  Major and minor are
+either an integer or * for all.  Access is a composition of r
+(read), w (write), and m (mknod).
+
+The root device cgroup starts with rwm to 'all'.  A child device
+cgroup gets a copy of the parent.  Administrators can then remove
+devices from the whitelist or add new entries.  A child cgroup can
+never receive a device access which is denied its parent.  However
+when a device access is removed from a parent it will not also be
+removed from the child(ren).
+
+2. User Interface
+
+An entry is added using devices.allow, and removed using
+devices.deny.  For instance
+
+       echo 'c 1:3 mr' > /cgroups/1/devices.allow
+
+allows cgroup 1 to read and mknod the device usually known as
+/dev/null.  Doing
+
+       echo a > /cgroups/1/devices.deny
+
+will remove the default 'a *:* mrw' entry.
+
+3. Security
+
+Any task can move itself between cgroups.  This clearly won't
+suffice, but we can decide the best way to adequately restrict
+movement as people get some experience with this.  We may just want
+to require CAP_SYS_ADMIN, which at least is a separate bit from
+CAP_MKNOD.  We may want to just refuse moving to a cgroup which
+isn't a descendent of the current one.  Or we may want to use
+CAP_MAC_ADMIN, since we really are trying to lock down root.
+
+CAP_SYS_ADMIN is needed to modify the whitelist or move another
+task to a new cgroup.  (Again we'll probably want to change that).
+
+A cgroup may not be granted more permissions than the cgroup's
+parent has.
diff --git a/Documentation/controllers/resource_counter.txt b/Documentation/controllers/resource_counter.txt
new file mode 100644 (file)
index 0000000..f196ac1
--- /dev/null
@@ -0,0 +1,181 @@
+
+               The Resource Counter
+
+The resource counter, declared at include/linux/res_counter.h,
+is supposed to facilitate the resource management by controllers
+by providing common stuff for accounting.
+
+This "stuff" includes the res_counter structure and routines
+to work with it.
+
+
+
+1. Crucial parts of the res_counter structure
+
+ a. unsigned long long usage
+
+       The usage value shows the amount of a resource that is consumed
+       by a group at a given time. The units of measurement should be
+       determined by the controller that uses this counter. E.g. it can
+       be bytes, items or any other unit the controller operates on.
+
+ b. unsigned long long max_usage
+
+       The maximal value of the usage over time.
+
+       This value is useful when gathering statistical information about
+       the particular group, as it shows the actual resource requirements
+       for a particular group, not just some usage snapshot.
+
+ c. unsigned long long limit
+
+       The maximal allowed amount of resource to consume by the group. In
+       case the group requests for more resources, so that the usage value
+       would exceed the limit, the resource allocation is rejected (see
+       the next section).
+
+ d. unsigned long long failcnt
+
+       The failcnt stands for "failures counter". This is the number of
+       resource allocation attempts that failed.
+
+ c. spinlock_t lock
+
+       Protects changes of the above values.
+
+
+
+2. Basic accounting routines
+
+ a. void res_counter_init(struct res_counter *rc)
+
+       Initializes the resource counter. As usual, should be the first
+       routine called for a new counter.
+
+ b. int res_counter_charge[_locked]
+                       (struct res_counter *rc, unsigned long val)
+
+       When a resource is about to be allocated it has to be accounted
+       with the appropriate resource counter (controller should determine
+       which one to use on its own). This operation is called "charging".
+
+       This is not very important which operation - resource allocation
+       or charging - is performed first, but
+         * if the allocation is performed first, this may create a
+           temporary resource over-usage by the time resource counter is
+           charged;
+         * if the charging is performed first, then it should be uncharged
+           on error path (if the one is called).
+
+ c. void res_counter_uncharge[_locked]
+                       (struct res_counter *rc, unsigned long val)
+
+       When a resource is released (freed) it should be de-accounted
+       from the resource counter it was accounted to.  This is called
+       "uncharging".
+
+    The _locked routines imply that the res_counter->lock is taken.
+
+
+ 2.1 Other accounting routines
+
+    There are more routines that may help you with common needs, like
+    checking whether the limit is reached or resetting the max_usage
+    value. They are all declared in include/linux/res_counter.h.
+
+
+
+3. Analyzing the resource counter registrations
+
+ a. If the failcnt value constantly grows, this means that the counter's
+    limit is too tight. Either the group is misbehaving and consumes too
+    many resources, or the configuration is not suitable for the group
+    and the limit should be increased.
+
+ b. The max_usage value can be used to quickly tune the group. One may
+    set the limits to maximal values and either load the container with
+    a common pattern or leave one for a while. After this the max_usage
+    value shows the amount of memory the container would require during
+    its common activity.
+
+    Setting the limit a bit above this value gives a pretty good
+    configuration that works in most of the cases.
+
+ c. If the max_usage is much less than the limit, but the failcnt value
+    is growing, then the group tries to allocate a big chunk of resource
+    at once.
+
+ d. If the max_usage is much less than the limit, but the failcnt value
+    is 0, then this group is given too high limit, that it does not
+    require. It is better to lower the limit a bit leaving more resource
+    for other groups.
+
+
+
+4. Communication with the control groups subsystem (cgroups)
+
+All the resource controllers that are using cgroups and resource counters
+should provide files (in the cgroup filesystem) to work with the resource
+counter fields. They are recommended to adhere to the following rules:
+
+ a. File names
+
+       Field name      File name
+       ---------------------------------------------------
+       usage           usage_in_<unit_of_measurement>
+       max_usage       max_usage_in_<unit_of_measurement>
+       limit           limit_in_<unit_of_measurement>
+       failcnt         failcnt
+       lock            no file :)
+
+ b. Reading from file should show the corresponding field value in the
+    appropriate format.
+
+ c. Writing to file
+
+       Field           Expected behavior
+       ----------------------------------
+       usage           prohibited
+       max_usage       reset to usage
+       limit           set the limit
+       failcnt         reset to zero
+
+
+
+5. Usage example
+
+ a. Declare a task group (take a look at cgroups subsystem for this) and
+    fold a res_counter into it
+
+       struct my_group {
+               struct res_counter res;
+
+               <other fields>
+       }
+
+ b. Put hooks in resource allocation/release paths
+
+       int alloc_something(...)
+       {
+               if (res_counter_charge(res_counter_ptr, amount) < 0)
+                       return -ENOMEM;
+
+               <allocate the resource and return to the caller>
+       }
+
+       void release_something(...)
+       {
+               res_counter_uncharge(res_counter_ptr, amount);
+
+               <release the resource>
+       }
+
+    In order to keep the usage value self-consistent, both the
+    "res_counter_ptr" and the "amount" in release_something() should be
+    the same as they were in the alloc_something() when the releasing
+    resource was allocated.
+
+ c. Provide the way to read res_counter values and set them (the cgroups
+    still can help with it).
+
+ c. Compile and run :)
index af3b925ece08945e6ca5ed37147022cfb45c0989..6c442d8426b5928569918ebd149f4818c5657ab1 100644 (file)
@@ -154,6 +154,11 @@ scaling_governor,          and by "echoing" the name of another
                                that some governors won't load - they only
                                work on some specific architectures or
                                processors.
+
+cpuinfo_cur_freq :             Current speed of the CPU, in KHz.
+
+scaling_available_frequencies : List of available frequencies, in KHz.
+
 scaling_min_freq and
 scaling_max_freq               show the current "policy limits" (in
                                kHz). By echoing new values into these
@@ -162,6 +167,15 @@ scaling_max_freq           show the current "policy limits" (in
                                first set scaling_max_freq, then
                                scaling_min_freq.
 
+affected_cpus :                        List of CPUs that require software coordination
+                               of frequency.
+
+related_cpus :                 List of CPUs that need some sort of frequency
+                               coordination, whether software or hardware.
+
+scaling_driver :               Hardware driver for cpufreq.
+
+scaling_cur_freq :             Current frequency of the CPU, in KHz.
 
 If you have selected the "userspace" governor which allows you to
 set the CPU operating frequency to a specific value, you can read out
index aa854b9b18cda8de6fae047540a529b55ca81405..fb7b361e6eea66c573af07d86c415ad4371dcb64 100644 (file)
@@ -171,6 +171,7 @@ files describing that cpuset:
  - memory_migrate flag: if set, move pages to cpusets nodes
  - cpu_exclusive flag: is cpu placement exclusive?
  - mem_exclusive flag: is memory placement exclusive?
+ - mem_hardwall flag:  is memory allocation hardwalled
  - memory_pressure: measure of how much paging pressure in cpuset
 
 In addition, the root cpuset only has the following file:
@@ -222,17 +223,18 @@ If a cpuset is cpu or mem exclusive, no other cpuset, other than
 a direct ancestor or descendent, may share any of the same CPUs or
 Memory Nodes.
 
-A cpuset that is mem_exclusive restricts kernel allocations for
-page, buffer and other data commonly shared by the kernel across
-multiple users.  All cpusets, whether mem_exclusive or not, restrict
-allocations of memory for user space.  This enables configuring a
-system so that several independent jobs can share common kernel data,
-such as file system pages, while isolating each jobs user allocation in
-its own cpuset.  To do this, construct a large mem_exclusive cpuset to
-hold all the jobs, and construct child, non-mem_exclusive cpusets for
-each individual job.  Only a small amount of typical kernel memory,
-such as requests from interrupt handlers, is allowed to be taken
-outside even a mem_exclusive cpuset.
+A cpuset that is mem_exclusive *or* mem_hardwall is "hardwalled",
+i.e. it restricts kernel allocations for page, buffer and other data
+commonly shared by the kernel across multiple users.  All cpusets,
+whether hardwalled or not, restrict allocations of memory for user
+space.  This enables configuring a system so that several independent
+jobs can share common kernel data, such as file system pages, while
+isolating each job's user allocation in its own cpuset.  To do this,
+construct a large mem_exclusive cpuset to hold all the jobs, and
+construct child, non-mem_exclusive cpusets for each individual job.
+Only a small amount of typical kernel memory, such as requests from
+interrupt handlers, is allowed to be taken outside even a
+mem_exclusive cpuset.
 
 
 1.5 What is memory_pressure ?
@@ -707,7 +709,7 @@ Now you want to do something with this cpuset.
 
 In this directory you can find several files:
 # ls
-cpus  cpu_exclusive  mems  mem_exclusive  tasks
+cpus  cpu_exclusive  mems  mem_exclusive mem_hardwall  tasks
 
 Reading them will give you information about the state of this cpuset:
 the CPUs and Memory Nodes it can use, the processes that are using
index 599fe55bf2970bb56b512f77d8ce5170d1e0199d..3c35d452b1a968439cdbb2b270bcaa75b26b762d 100644 (file)
@@ -138,6 +138,24 @@ Who:       Kay Sievers <kay.sievers@suse.de>
 
 ---------------------------
 
+What:  find_task_by_pid
+When:  2.6.26
+Why:   With pid namespaces, calling this funciton will return the
+       wrong task when called from inside a namespace.
+
+       The best way to save a task pid and find a task by this
+       pid later, is to find this task's struct pid pointer (or get
+       it directly from the task) and call pid_task() later.
+
+       If someone really needs to get a task by its pid_t, then
+       he most likely needs the find_task_by_vpid() to get the
+       task from the same namespace as the current task is in, but
+       this may be not so in general.
+
+Who:   Pavel Emelyanov <xemul@openvz.org>
+
+---------------------------
+
 What:  ACPI procfs interface
 When:  July 2008
 Why:   ACPI sysfs conversion should be finished by January 2008.
index 2a99116edc47335f6ab6f50859de0a8284750cdd..dbc3c6a3650f5c29b24000d69e1c9cb7973b4988 100644 (file)
@@ -463,11 +463,17 @@ SwapTotal:           0 kB
 SwapFree:            0 kB
 Dirty:             968 kB
 Writeback:           0 kB
+AnonPages:      861800 kB
 Mapped:         280372 kB
-Slab:           684068 kB
+Slab:           284364 kB
+SReclaimable:   159856 kB
+SUnreclaim:     124508 kB
+PageTables:      24448 kB
+NFS_Unstable:        0 kB
+Bounce:              0 kB
+WritebackTmp:        0 kB
 CommitLimit:   7669796 kB
 Committed_AS:   100056 kB
-PageTables:      24448 kB
 VmallocTotal:   112216 kB
 VmallocUsed:       428 kB
 VmallocChunk:   111088 kB
@@ -503,8 +509,17 @@ VmallocChunk:   111088 kB
               on the disk
        Dirty: Memory which is waiting to get written back to the disk
    Writeback: Memory which is actively being written back to the disk
+   AnonPages: Non-file backed pages mapped into userspace page tables
       Mapped: files which have been mmaped, such as libraries
         Slab: in-kernel data structures cache
+SReclaimable: Part of Slab, that might be reclaimed, such as caches
+  SUnreclaim: Part of Slab, that cannot be reclaimed on memory pressure
+  PageTables: amount of memory dedicated to the lowest level of page
+              tables.
+NFS_Unstable: NFS pages sent to the server, but not yet committed to stable
+             storage
+      Bounce: Memory used for block device "bounce buffers"
+WritebackTmp: Memory used by FUSE for temporary writeback buffers
  CommitLimit: Based on the overcommit ratio ('vm.overcommit_ratio'),
               this is the total amount of  memory currently available to
               be allocated on the system. This limit is only adhered to
@@ -531,8 +546,6 @@ Committed_AS: The amount of memory presently allocated on the system.
               above) will not be permitted. This is useful if one needs
               to guarantee that processes will not fail due to lack of
               memory once that memory has been successfully allocated.
-  PageTables: amount of memory dedicated to the lowest level of page
-              tables.
 VmallocTotal: total size of vmalloc memory area
  VmallocUsed: amount of vmalloc area which is used
 VmallocChunk: largest contigious block of vmalloc area which is free
index bfb0a5520817c5bbe770d35af48c0381b5b6dc6c..ee75cbace28d529cb690e573ec4c2cb67f75bd0f 100644 (file)
@@ -164,7 +164,8 @@ I2C device drivers using this binding model work just like any other
 kind of driver in Linux:  they provide a probe() method to bind to
 those devices, and a remove() method to unbind.
 
-       static int foo_probe(struct i2c_client *client);
+       static int foo_probe(struct i2c_client *client,
+                            const struct i2c_device_id *id);
        static int foo_remove(struct i2c_client *client);
 
 Remember that the i2c_driver does not create those client handles.  The
index 0fac3465f2e38e5612a31cfa83e83cdcad95e83e..95ad15c3b01f3256b8f06efb6a1a5f3905d02952 100644 (file)
@@ -40,9 +40,17 @@ Protocol 2.05:       (Kernel 2.6.20) Make protected mode kernel relocatable.
                Introduce relocatable_kernel and kernel_alignment fields.
 
 Protocol 2.06: (Kernel 2.6.22) Added a field that contains the size of
-               the boot command line
+               the boot command line.
 
-Protocol 2.09: (kernel 2.6.26) Added a field of 64-bit physical
+Protocol 2.07: (Kernel 2.6.24) Added paravirtualised boot protocol.
+               Introduced hardware_subarch and hardware_subarch_data
+               and KEEP_SEGMENTS flag in load_flags.
+
+Protocol 2.08: (Kernel 2.6.26) Added crc32 checksum and ELF format
+               payload. Introduced payload_offset and payload length
+               fields to aid in locating the payload.
+
+Protocol 2.09: (Kernel 2.6.26) Added a field of 64-bit physical
                pointer to single linked list of struct setup_data.
 
 **** MEMORY LAYOUT
index e5f3d918316f5d421cafc88da6b9baf005c929ac..a3c35446e755c7c5bedaacf47be5f6050aad2145 100644 (file)
@@ -496,6 +496,11 @@ and is between 256 and 4096 characters. It is defined in the file
                        switching to the matching ttyS device later.  The
                        options are the same as for ttyS, above.
 
+                If the device connected to the port is not a TTY but a braille
+                device, prepend "brl," before the device type, for instance
+                       console=brl,ttyS0
+               For now, only VisioBraille is supported.
+
        earlycon=       [KNL] Output early console device and options.
                uart[8250],io,<addr>[,options]
                uart[8250],mmio,<addr>[,options]
@@ -556,6 +561,8 @@ and is between 256 and 4096 characters. It is defined in the file
                        1 will print _a lot_ more information - normally
                        only useful to kernel developers.
 
+       debug_objects   [KNL] Enable object debugging
+
        decnet.addr=    [HW,NET]
                        Format: <area>[,<node>]
                        See also Documentation/networking/decnet.txt.
@@ -627,8 +634,7 @@ and is between 256 and 4096 characters. It is defined in the file
        eata=           [HW,SCSI]
 
        edd=            [EDD]
-                       Format: {"of[f]" | "sk[ipmbr]"}
-                       See comment in arch/i386/boot/edd.S
+                       Format: {"off" | "on" | "skip[mbr]"}
 
        eisa_irq_edge=  [PARISC,HW]
                        See header of drivers/parisc/eisa.c.
@@ -1389,6 +1395,13 @@ and is between 256 and 4096 characters. It is defined in the file
 
        nr_uarts=       [SERIAL] maximum number of UARTs to be registered.
 
+       olpc_ec_timeout= [OLPC] ms delay when issuing EC commands
+                       Rather than timing out after 20 ms if an EC
+                       command is not properly ACKed, override the length
+                       of the timeout.  We have interrupts disabled while
+                       waiting for the ACK, so if this is set too high
+                       interrupts *may* be lost!
+
        opl3=           [HW,OSS]
                        Format: <io>
 
index 266955d23ee6eb9bff2e98ad1bc6d2bc916d9369..09b55e4617404437fb2806c5cabccf58f1c3aa40 100644 (file)
@@ -11,26 +11,29 @@ request_key*():
 
        struct key *request_key(const struct key_type *type,
                                const char *description,
-                               const char *callout_string);
+                               const char *callout_info);
 
 or:
 
        struct key *request_key_with_auxdata(const struct key_type *type,
                                             const char *description,
-                                            const char *callout_string,
+                                            const char *callout_info,
+                                            size_t callout_len,
                                             void *aux);
 
 or:
 
        struct key *request_key_async(const struct key_type *type,
                                      const char *description,
-                                     const char *callout_string);
+                                     const char *callout_info,
+                                     size_t callout_len);
 
 or:
 
        struct key *request_key_async_with_auxdata(const struct key_type *type,
                                                   const char *description,
-                                                  const char *callout_string,
+                                                  const char *callout_info,
+                                                  size_t callout_len,
                                                   void *aux);
 
 Or by userspace invoking the request_key system call:
index 51652d39e61c3d0d25bba568699f249f6e1fa0f4..d5c7a57d17007fa0f43558b270b0e4c302d5f8aa 100644 (file)
@@ -170,7 +170,8 @@ The key service provides a number of features besides keys:
      amount of description and payload space that can be consumed.
 
      The user can view information on this and other statistics through procfs
-     files.
+     files.  The root user may also alter the quota limits through sysctl files
+     (see the section "New procfs files").
 
      Process-specific and thread-specific keyrings are not counted towards a
      user's quota.
@@ -329,6 +330,27 @@ about the status of the key service:
        <bytes>/<max>           Key size quota
 
 
+Four new sysctl files have been added also for the purpose of controlling the
+quota limits on keys:
+
+ (*) /proc/sys/kernel/keys/root_maxkeys
+     /proc/sys/kernel/keys/root_maxbytes
+
+     These files hold the maximum number of keys that root may have and the
+     maximum total number of bytes of data that root may have stored in those
+     keys.
+
+ (*) /proc/sys/kernel/keys/maxkeys
+     /proc/sys/kernel/keys/maxbytes
+
+     These files hold the maximum number of keys that each non-root user may
+     have and the maximum total number of bytes of data that each of those
+     users may have stored in their keys.
+
+Root may alter these by writing each new limit as a decimal number string to
+the appropriate file.
+
+
 ===============================
 USERSPACE SYSTEM CALL INTERFACE
 ===============================
@@ -711,6 +733,27 @@ The keyctl syscall functions are:
      The assumed authoritative key is inherited across fork and exec.
 
 
+ (*) Get the LSM security context attached to a key.
+
+       long keyctl(KEYCTL_GET_SECURITY, key_serial_t key, char *buffer,
+                   size_t buflen)
+
+     This function returns a string that represents the LSM security context
+     attached to a key in the buffer provided.
+
+     Unless there's an error, it always returns the amount of data it could
+     produce, even if that's too big for the buffer, but it won't copy more
+     than requested to userspace. If the buffer pointer is NULL then no copy
+     will take place.
+
+     A NUL character is included at the end of the string if the buffer is
+     sufficiently big.  This is included in the returned count.  If no LSM is
+     in force then an empty string will be returned.
+
+     A process must have view permission on the key for this function to be
+     successful.
+
+
 ===============
 KERNEL SERVICES
 ===============
@@ -771,7 +814,7 @@ payload contents" for more information.
 
        struct key *request_key(const struct key_type *type,
                                const char *description,
-                               const char *callout_string);
+                               const char *callout_info);
 
     This is used to request a key or keyring with a description that matches
     the description specified according to the key type's match function. This
@@ -793,24 +836,28 @@ payload contents" for more information.
 
        struct key *request_key_with_auxdata(const struct key_type *type,
                                             const char *description,
-                                            const char *callout_string,
+                                            const void *callout_info,
+                                            size_t callout_len,
                                             void *aux);
 
     This is identical to request_key(), except that the auxiliary data is
-    passed to the key_type->request_key() op if it exists.
+    passed to the key_type->request_key() op if it exists, and the callout_info
+    is a blob of length callout_len, if given (the length may be 0).
 
 
 (*) A key can be requested asynchronously by calling one of:
 
        struct key *request_key_async(const struct key_type *type,
                                      const char *description,
-                                     const char *callout_string);
+                                     const void *callout_info,
+                                     size_t callout_len);
 
     or:
 
        struct key *request_key_async_with_auxdata(const struct key_type *type,
                                                   const char *description,
-                                                  const char *callout_string,
+                                                  const char *callout_info,
+                                                  size_t callout_len,
                                                   void *aux);
 
     which are asynchronous equivalents of request_key() and
index 7f60dfe642caf9a65421f49b3cf9c342b79705dd..b152e81da5923e5150de6ba6a67d6ec37219ca43 100644 (file)
@@ -253,6 +253,10 @@ characters, each representing a particular tainted value.
 
   8: 'D' if the kernel has died recently, i.e. there was an OOPS or BUG.
 
+  9: 'A' if the ACPI table has been overridden.
+
+ 10: 'W' if a warning has previously been issued by the kernel.
+
 The primary reason for the 'Tainted: ' string is to tell kernel
 debuggers if this is a clean kernel or if anything unusual has
 occurred.  Tainting is permanent: even if an offending module is
index fd4c32a031c9f5e5381b440379ea70ca9e85ff7e..0bbee38acd263f6e88605ac71e3bd12c8ca3bf70 100644 (file)
@@ -795,6 +795,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
          lg-lw         LG LW20/LW25 laptop
          tcl           TCL S700
          clevo         Clevo laptops (m520G, m665n)
+         medion        Medion Rim 2150
          test          for testing/debugging purpose, almost all controls can be
                        adjusted.  Appearing only when compiled with
                        $CONFIG_SND_DEBUG=y
index 10c8f6922ef40d7a0a49b85ae6367be1a0edfd91..5ce0952aa06546096fc165d9562f35565ed17025 100644 (file)
@@ -85,6 +85,8 @@ On all -  write a character to /proc/sysrq-trigger.  e.g.:
 'k'     - Secure Access Key (SAK) Kills all programs on the current virtual
           console. NOTE: See important comments below in SAK section.
 
+'l'     - Shows a stack backtrace for all active CPUs.
+
 'm'     - Will dump current memory info to your console.
 
 'n'    - Used to make RT tasks nice-able
index 44d84dd15ad672d55b4a93db652f34d74cb3a664..67937df1e974b0e787199c04d996ab084786844d 100644 (file)
 127 -> Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM [0000:5071,0000:507B,5ace:5070,5ace:5090]
 128 -> Beholder BeholdTV Columbus TVFM          [0000:5201]
 129 -> Beholder BeholdTV 607 / BeholdTV 609     [5ace:6070,5ace:6071,5ace:6072,5ace:6073,5ace:6090,5ace:6091,5ace:6092,5ace:6093]
-130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193]
+130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193,5ace:6191]
 131 -> Twinhan Hybrid DTV-DVB 3056 PCI          [1822:0022]
 132 -> Genius TVGO AM11MCE
 133 -> NXP Snake DVB-S reference design
 139 -> Compro VideoMate T750                    [185b:c900]
 140 -> Avermedia DVB-S Pro A700                 [1461:a7a1]
 141 -> Avermedia DVB-S Hybrid+FM A700           [1461:a7a2]
+142 -> Beholder BeholdTV H6                     [5ace:6290]
diff --git a/Documentation/video4linux/cx18.txt b/Documentation/video4linux/cx18.txt
new file mode 100644 (file)
index 0000000..077d56e
--- /dev/null
@@ -0,0 +1,34 @@
+Some notes regarding the cx18 driver for the Conexant CX23418 MPEG
+encoder chip:
+
+1) The only hardware currently supported is the Hauppauge HVR-1600.
+
+2) Some people have problems getting the i2c bus to work. Cause unknown.
+   The symptom is that the eeprom cannot be read and the card is
+   unusable.
+
+3) The audio from the analog tuner is mono only. Probably caused by
+   incorrect audio register information in the datasheet. We are
+   waiting for updated information from Conexant.
+
+4) VBI (raw or sliced) has not yet been implemented.
+
+5) MPEG indexing is not yet implemented.
+
+6) The driver is still a bit rough around the edges, this should
+   improve over time.
+
+
+Firmware:
+
+The firmware needs to be extracted from the Windows Hauppauge HVR-1600
+driver, available here:
+
+http://hauppauge.lightpath.net/software/install_cd/hauppauge_cd_3.4d1.zip
+
+Unzip, then copy the following files to the firmware directory
+and rename them as follows:
+
+Drivers/Driver18/hcw18apu.rom -> v4l-cx23418-apu.fw
+Drivers/Driver18/hcw18enc.rom -> v4l-cx23418-cpu.fw
+Drivers/Driver18/hcw18mlC.rom -> v4l-cx23418-dig.fw
index c1dd1ae7b1335d9de927e6a7731d72066424660d..f822c04f1aeae77d2df2a43de57e94777b998fa1 100644 (file)
@@ -752,11 +752,13 @@ W:        http://atmelwlandriver.sourceforge.net/
 S:     Maintained
 
 AUDIT SUBSYSTEM
-P:     David Woodhouse
-M:     dwmw2@infradead.org
+P:     Al Viro
+M:     viro@zeniv.linux.org.uk
+P:     Eric Paris
+M:     eparis@redhat.com
 L:     linux-audit@redhat.com (subscribers-only)
 W:     http://people.redhat.com/sgrubb/audit/
-T:     git kernel.org:/pub/scm/linux/kernel/git/dwmw2/audit-2.6.git
+T:     git git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current.git
 S:     Maintained
 
 AUXILIARY DISPLAY DRIVERS
@@ -2694,7 +2696,7 @@ P:        David Howells
 M:     dhowells@redhat.com
 P:     Koichi Yasutake
 M:     yasutake.koichi@jp.panasonic.com
-L:     linux-am33-list@redhat.com
+L:     linux-am33-list@redhat.com (moderated for non-subscribers)
 W:     ftp://ftp.redhat.com/pub/redhat/gnupro/AM33/
 S:     Maintained
 
@@ -2757,7 +2759,7 @@ M:        rubini@ipvvis.unipv.it
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 
-MOXA SMARTIO/INDUSTIO SERIAL CARD (MXSER 2.0)
+MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
 P:     Jiri Slaby
 M:     jirislaby@gmail.com
 L:     linux-kernel@vger.kernel.org
@@ -3114,6 +3116,7 @@ P:        Jesse Barnes
 M:     jbarnes@virtuousgeek.org
 L:     linux-kernel@vger.kernel.org
 L:     linux-pci@atrey.karlin.mff.cuni.cz
+T:     git kernel.org:/pub/scm/linux/kernel/git/jbarnes/pci-2.6.git
 S:     Supported
 
 PCI HOTPLUG CORE
@@ -3740,42 +3743,6 @@ M:       chrisw@sous-sol.org
 L:     stable@kernel.org
 S:     Maintained
 
-TPM DEVICE DRIVER
-P:     Kylene Hall
-M:     tpmdd-devel@lists.sourceforge.net
-W:     http://tpmdd.sourceforge.net
-P:     Marcel Selhorst
-M:     tpm@selhorst.net
-W:     http://www.prosec.rub.de/tpm/
-L:     tpmdd-devel@lists.sourceforge.net
-S:     Maintained
-
-Telecom Clock Driver for MCPL0010
-P:     Mark Gross
-M:     mark.gross@intel.com
-S:     Supported
-
-TENSILICA XTENSA PORT (xtensa):
-P:     Chris Zankel
-M:     chris@zankel.net
-S:     Maintained
-
-THINKPAD ACPI EXTRAS DRIVER
-P:     Henrique de Moraes Holschuh
-M:     ibm-acpi@hmh.eng.br
-L:     ibm-acpi-devel@lists.sourceforge.net
-W:     http://ibm-acpi.sourceforge.net
-W:     http://thinkwiki.org/wiki/Ibm-acpi
-T:     git repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git
-S:     Maintained
-
-UltraSPARC (sparc64):
-P:     David S. Miller
-M:     davem@davemloft.net
-L:     sparclinux@vger.kernel.org
-T:     git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git
-S:     Maintained
-
 SHARP LH SUPPORT (LH7952X & LH7A40X)
 P:     Marc Singer
 M:     elf@buici.com
@@ -3872,6 +3839,12 @@ P:       Christoph Hellwig
 M:     hch@infradead.org
 S:     Maintained
 
+TASKSTATS STATISTICS INTERFACE
+P:     Shailabh Nagar
+M:     nagar@watson.ibm.com
+L:     linux-kernel@vger.kernel.org
+S:     Maintained
+
 TC CLASSIFIER
 P:     Jamal Hadi Salim
 M:     hadi@cyberus.ca
@@ -3894,6 +3867,25 @@ M:       andy@greyhouse.net
 L:     netdev@vger.kernel.org
 S:     Supported
 
+Telecom Clock Driver for MCPL0010
+P:     Mark Gross
+M:     mark.gross@intel.com
+S:     Supported
+
+TENSILICA XTENSA PORT (xtensa):
+P:     Chris Zankel
+M:     chris@zankel.net
+S:     Maintained
+
+THINKPAD ACPI EXTRAS DRIVER
+P:     Henrique de Moraes Holschuh
+M:     ibm-acpi@hmh.eng.br
+L:     ibm-acpi-devel@lists.sourceforge.net
+W:     http://ibm-acpi.sourceforge.net
+W:     http://thinkwiki.org/wiki/Ibm-acpi
+T:     git repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git
+S:     Maintained
+
 TI FLASH MEDIA INTERFACE DRIVER
 P:      Alex Dubov
 M:      oakad@yahoo.com
@@ -3911,12 +3903,6 @@ P:       Deepak Saxena
 M:     dsaxena@plexity.net
 S:     Maintained
 
-TASKSTATS STATISTICS INTERFACE
-P:     Shailabh Nagar
-M:     nagar@watson.ibm.com
-L:     linux-kernel@vger.kernel.org
-S:     Maintained
-
 TIPC NETWORK LAYER
 P:     Per Liden
 M:     per.liden@ericsson.com
@@ -3950,6 +3936,16 @@ L:       tlinux-users@tce.toshiba-dme.co.jp
 W:     http://www.buzzard.org.uk/toshiba/
 S:     Maintained
 
+TPM DEVICE DRIVER
+P:     Kylene Hall
+M:     tpmdd-devel@lists.sourceforge.net
+W:     http://tpmdd.sourceforge.net
+P:     Marcel Selhorst
+M:     tpm@selhorst.net
+W:     http://www.prosec.rub.de/tpm/
+L:     tpmdd-devel@lists.sourceforge.net
+S:     Maintained
+
 TRIDENT 4DWAVE/SIS 7018 PCI AUDIO CORE
 P:     Muli Ben-Yehuda
 M:     mulix@mulix.org
@@ -3962,6 +3958,12 @@ M:       trivial@kernel.org
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 
+TTY LAYER
+P:     Alan Cox
+M:     alan@lxorguk.ukuu.org.uk
+L:     linux-kernel@vger.kernel.org
+S:     Maintained
+
 TULIP NETWORK DRIVERS
 P:     Grant Grundler
 M:     grundler@parisc-linux.org
@@ -4130,6 +4132,20 @@ L:      linux-usb@vger.kernel.org
 W:     http://www.chello.nl/~j.vreeken/se401/
 S:     Maintained
 
+USB SERIAL BELKIN F5U103 DRIVER
+P:     William Greathouse
+M:     wgreathouse@smva.com
+L:      linux-usb@vger.kernel.org
+S:     Maintained
+
+USB SERIAL CYPRESS M8 DRIVER
+P:     Lonnie Mendez
+M:     dignome@gmail.com
+L:      linux-usb@vger.kernel.org
+S:     Maintained
+W:     http://geocities.com/i0xox0i
+W:     http://firstlight.net/cvs
+
 USB SERIAL CYBERJACK DRIVER
 P:     Matthias Bruestle and Harald Welte
 M:     support@reiner-sct.com
@@ -4149,20 +4165,6 @@ M:       gregkh@suse.de
 L:      linux-usb@vger.kernel.org
 S:     Supported
 
-USB SERIAL BELKIN F5U103 DRIVER
-P:     William Greathouse
-M:     wgreathouse@smva.com
-L:      linux-usb@vger.kernel.org
-S:     Maintained
-
-USB SERIAL CYPRESS M8 DRIVER
-P:     Lonnie Mendez
-M:     dignome@gmail.com
-L:      linux-usb@vger.kernel.org
-S:     Maintained
-W:     http://geocities.com/i0xox0i
-W:     http://firstlight.net/cvs
-
 USB SERIAL EMPEG EMPEG-CAR MARK I/II DRIVER
 P:     Gary Brubaker
 M:     xavyer@ix.netcom.com
@@ -4265,7 +4267,7 @@ M:        gregkh@suse.de
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 
-FAT/VFAT/MSDOS FILESYSTEM:
+VFAT/FAT/MSDOS FILESYSTEM:
 P:     OGAWA Hirofumi
 M:     hirofumi@mail.parknet.co.jp
 L:     linux-kernel@vger.kernel.org
@@ -4310,6 +4312,13 @@ M:       dushistov@mail.ru
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 
+UltraSPARC (sparc64):
+P:     David S. Miller
+M:     davem@davemloft.net
+L:     sparclinux@vger.kernel.org
+T:     git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git
+S:     Maintained
+
 USB DIAMOND RIO500 DRIVER
 P:     Cesar Miquel
 M:     miquel@df.uba.ar
index 694c9af520bbed3e9a36a6c16aa693f541b192b8..3ea332b009e511f785349c725e716052d42877ef 100644 (file)
@@ -36,3 +36,6 @@ config HAVE_KPROBES
 
 config HAVE_KRETPROBES
        def_bool n
+
+config HAVE_DMA_ATTRS
+       def_bool n
index 6c56c754a0b53c2947f662c0e3adde986ebdc513..4b18cd94d59d5060acfac02ad276101579ca481a 100644 (file)
@@ -8,13 +8,9 @@
 #include <linux/stddef.h>
 #include <linux/sched.h>
 #include <linux/ptrace.h>
+#include <linux/kbuild.h>
 #include <asm/io.h>
 
-#define DEFINE(sym, val) \
-        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : : )
-
 void foo(void)
 {
        DEFINE(TI_TASK, offsetof(struct thread_info, task));
index baf57563b14c42c54cc433d0bea067c9330871cc..36ab22a7ea124920f7f0cf8617deacf6906623a9 100644 (file)
@@ -514,8 +514,8 @@ sys_pciconfig_iobase(long which, unsigned long bus, unsigned long dfn)
 
 void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
 {
-       unsigned long start = pci_resource_start(dev, bar);
-       unsigned long len = pci_resource_len(dev, bar);
+       resource_size_t start = pci_resource_start(dev, bar);
+       resource_size_t len = pci_resource_len(dev, bar);
        unsigned long flags = pci_resource_flags(dev, bar);
 
        if (!len || !start)
index dc030cfe5009640c1a7891f2ce632fea9cf3f816..5e68420f468046c306386e1f05275d0902ae3aea 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.25-rc3
-# Sun Mar  9 06:33:33 2008
+# Linux kernel version: 2.6.25
+# Sun Apr 20 00:29:49 2008
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -51,7 +51,8 @@ CONFIG_FAIR_GROUP_SCHED=y
 # CONFIG_RT_GROUP_SCHED is not set
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
-# CONFIG_SYSFS_DEPRECATED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 # CONFIG_BLK_DEV_INITRD is not set
@@ -85,6 +86,7 @@ CONFIG_SLAB=y
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
 CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -115,7 +117,6 @@ CONFIG_IOSCHED_NOOP=y
 CONFIG_DEFAULT_NOOP=y
 CONFIG_DEFAULT_IOSCHED="noop"
 CONFIG_CLASSIC_RCU=y
-# CONFIG_PREEMPT_RCU is not set
 
 #
 # System Type
@@ -320,8 +321,6 @@ CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
 # CONFIG_IP_DCCP is not set
@@ -383,7 +382,6 @@ CONFIG_IEEE80211=m
 CONFIG_IEEE80211_CRYPT_WEP=m
 # CONFIG_IEEE80211_CRYPT_CCMP is not set
 # CONFIG_IEEE80211_CRYPT_TKIP is not set
-# CONFIG_IEEE80211_SOFTMAC is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -503,7 +501,7 @@ CONFIG_IDE_MAX_HWIFS=2
 CONFIG_BLK_DEV_IDE=m
 
 #
-# Please see Documentation/ide.txt for help/info on IDE drives
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
 #
 # CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=m
@@ -518,10 +516,9 @@ CONFIG_IDE_PROC_FS=y
 #
 # IDE chipset support/bugfixes
 #
-CONFIG_IDE_GENERIC=m
 # CONFIG_BLK_DEV_PLATFORM is not set
 # CONFIG_BLK_DEV_IDEDMA is not set
-CONFIG_IDE_ARCH_OBSOLETE_INIT=y
+# CONFIG_BLK_DEV_HD_ONLY is not set
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -562,6 +559,7 @@ CONFIG_NETDEV_10000=y
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
 # CONFIG_NET_PCMCIA is not set
 # CONFIG_WAN is not set
 # CONFIG_PPP is not set
@@ -707,6 +705,8 @@ CONFIG_SSB_POSSIBLE=y
 #
 # CONFIG_MFD_SM501 is not set
 # CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
 
 #
 # Multimedia devices
@@ -745,6 +745,7 @@ CONFIG_FB_TILEBLITTING=y
 CONFIG_FB_PXA=y
 CONFIG_FB_PXA_PARAMETERS=y
 CONFIG_FB_MBX=m
+# CONFIG_FB_METRONOME is not set
 CONFIG_FB_VIRTUAL=m
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
@@ -891,7 +892,6 @@ CONFIG_RTC_LIB=y
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_DNOTIFY is not set
 CONFIG_INOTIFY=y
index 0a0d2479274b6c749c905aa5efcf4c2beb01b407..4a881258bb171f7c14828d12fdc4ef9bf91b0186 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/thread_info.h>
 #include <asm/memory.h>
 #include <asm/procinfo.h>
+#include <linux/kbuild.h>
 
 /*
  * Make sure that the compiler and target are compatible.
 #error    Known good compilers: 3.3
 #endif
 
-/* Use marker if you need to separate the values later */
-
-#define DEFINE(sym, val) \
-        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : : )
-
 int main(void)
 {
   DEFINE(TSK_ACTIVE_MM,                offsetof(struct task_struct, active_mm));
index e2e934c38080240ef5843b30273f114f2a213347..64c420805e6f4e2b7945cef4bcff38e3c4e2f576 100644 (file)
@@ -35,7 +35,7 @@ create_proc_entries(void)
 {
        struct proc_dir_entry* tags_entry;
 
-       tags_entry = create_proc_read_entry("atags", 0400, &proc_root, read_buffer, &tags_buffer);
+       tags_entry = create_proc_read_entry("atags", 0400, NULL, read_buffer, &tags_buffer);
        if (!tags_entry)
                return -ENOMEM;
 
index f56d48c451ea8dc4438a92e0539de21a7b3fc100..a53c0aba5c142b53295ca2563785bde904dc72b1 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
@@ -723,17 +724,14 @@ unsigned int __ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
        return address;
 }
 
-static int ecard_prints(char *buffer, ecard_t *ec)
+static int ecard_prints(struct seq_file *m, ecard_t *ec)
 {
-       char *start = buffer;
-
-       buffer += sprintf(buffer, "  %d: %s ", ec->slot_no,
-                         ec->easi ? "EASI" : "    ");
+       seq_printf(m, "  %d: %s ", ec->slot_no, ec->easi ? "EASI" : "    ");
 
        if (ec->cid.id == 0) {
                struct in_chunk_dir incd;
 
-               buffer += sprintf(buffer, "[%04X:%04X] ",
+               seq_printf(m, "[%04X:%04X] ",
                        ec->cid.manufacturer, ec->cid.product);
 
                if (!ec->card_desc && ec->cid.cd &&
@@ -744,43 +742,43 @@ static int ecard_prints(char *buffer, ecard_t *ec)
                                strcpy((char *)ec->card_desc, incd.d.string);
                }
 
-               buffer += sprintf(buffer, "%s\n", ec->card_desc ? ec->card_desc : "*unknown*");
+               seq_printf(m, "%s\n", ec->card_desc ? ec->card_desc : "*unknown*");
        } else
-               buffer += sprintf(buffer, "Simple card %d\n", ec->cid.id);
+               seq_printf(m, "Simple card %d\n", ec->cid.id);
 
-       return buffer - start;
+       return 0;
 }
 
-static int get_ecard_dev_info(char *buf, char **start, off_t pos, int count)
+static int ecard_devices_proc_show(struct seq_file *m, void *v)
 {
        ecard_t *ec = cards;
-       off_t at = 0;
-       int len, cnt;
-
-       cnt = 0;
-       while (ec && count > cnt) {
-               len = ecard_prints(buf, ec);
-               at += len;
-               if (at >= pos) {
-                       if (!*start) {
-                               *start = buf + (pos - (at - len));
-                               cnt = at - pos;
-                       } else
-                               cnt += len;
-                       buf += len;
-               }
+
+       while (ec) {
+               ecard_prints(m, ec);
                ec = ec->next;
        }
-       return (count > cnt) ? cnt : count;
+       return 0;
 }
 
+static int ecard_devices_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, ecard_devices_proc_show, NULL);
+}
+
+static const struct file_operations bus_ecard_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = ecard_devices_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
 static struct proc_dir_entry *proc_bus_ecard_dir = NULL;
 
 static void ecard_proc_init(void)
 {
-       proc_bus_ecard_dir = proc_mkdir("ecard", proc_bus);
-       create_proc_info_entry("devices", 0, proc_bus_ecard_dir,
-               get_ecard_dev_info);
+       proc_bus_ecard_dir = proc_mkdir("bus/ecard", NULL);
+       proc_create("devices", 0, proc_bus_ecard_dir, &bus_ecard_proc_fops);
 }
 
 #define ec_set_resource(ec,nr,st,sz)                           \
index d51bc8b60557243cda3bef93c1e5d29a2c198eca..b4565bb133c1ebeadd6c3a8d3b3a1afdd9015a7e 100644 (file)
@@ -1176,7 +1176,7 @@ space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
         * *S (bit 20) updates condition codes
         * ADC/SBC/RSC reads the C flag
         */
-       insn &= 0xfff00ff0;     /* Rn = r0, Rd = r0 */
+       insn &= 0xfff00fff;     /* Rn = r0, Rd = r0 */
        asi->insn[0] = insn;
        asi->insn_handler = (insn & (1 << 20)) ?  /* S-bit */
                        emulate_alu_imm_rwflags : emulate_alu_imm_rflags;
index 13e371aad8792686df6fee77d0642fa3030f8a69..5593dd207216bd0d2d1d8319eb8ab06e2bc13714 100644 (file)
@@ -66,7 +66,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
                        return -ENOMEM;
                for (is = 0; is < MAX_INSN_SIZE; ++is)
                        p->ainsn.insn[is] = tmp_insn[is];
-               flush_insns(&p->ainsn.insn, MAX_INSN_SIZE);
+               flush_insns(p->ainsn.insn, MAX_INSN_SIZE);
                break;
 
        case INSN_GOOD_NO_SLOT: /* instruction doesn't need insn slot */
index f1a80d74a4b659bde31a4402453f0bfa0232c19b..be526746e01e496d46a3e49db1b06494c7f9b1bf 100644 (file)
@@ -246,7 +246,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
                }
 
                mmc0_data = *data;
-               at91_clock_associate("mci0_clk", &at91cap9_mmc1_device.dev, "mci_clk");
+               at91_clock_associate("mci0_clk", &at91cap9_mmc0_device.dev, "mci_clk");
                platform_device_register(&at91cap9_mmc0_device);
        } else {                        /* MCI1 */
                /* CLK */
index b6454c52596227a640c77b15ec3699d05fcd1b3e..719667e25c981f01f8261e37746d3f5cdbb22d65 100644 (file)
@@ -308,7 +308,7 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
                }
 
                mmc0_data = *data;
-               at91_clock_associate("mci0_clk", &at91sam9263_mmc1_device.dev, "mci_clk");
+               at91_clock_associate("mci0_clk", &at91sam9263_mmc0_device.dev, "mci_clk");
                platform_device_register(&at91sam9263_mmc0_device);
        } else {                        /* MCI1 */
                /* CLK */
index 26fea4dcc3a013edbd14f41c58c88b3b8b098e2d..81f1ebb4e964ed3c3228bb4c1b2a370b982ca39b 100644 (file)
@@ -79,8 +79,7 @@ static struct at91_udc_data __initdata csb337_udc_data = {
 
 static struct i2c_board_info __initdata csb337_i2c_devices[] = {
        {
-               I2C_BOARD_INFO("rtc-ds1307", 0x68),
-               .type   = "ds1307",
+               I2C_BOARD_INFO("ds1307", 0x68),
        },
 };
 
index 0a897efeba8e5321dc8fdfec5da831aa7a554f73..c1a813c7169b63f86f932b53bd3945efc1535204 100644 (file)
@@ -132,8 +132,7 @@ static struct i2c_board_info __initdata dk_i2c_devices[] = {
                I2C_BOARD_INFO("x9429", 0x28),
        },
        {
-               I2C_BOARD_INFO("at24c", 0x50),
-               .type   = "24c1024",
+               I2C_BOARD_INFO("24c1024", 0x50),
        }
 };
 
index b7b79bb9d6c4b09bd464225adb1e15a415ff16d8..af1a1d8ecc303a31d59841536f9c896acdd82b34 100644 (file)
@@ -93,8 +93,7 @@ static struct at91_mmc_data __initdata eb9200_mmc_data = {
 
 static struct i2c_board_info __initdata eb9200_i2c_devices[] = {
        {
-               I2C_BOARD_INFO("at24c", 0x50),
-               .type   = "24c512",
+               I2C_BOARD_INFO("24c512", 0x50),
        },
 };
 
index 39733b6992aa3126ee5e715dbaa0ef97faceefd3..aa863c1577087fa1bb0ba8ea5d26d8b37572c96b 100644 (file)
@@ -61,6 +61,15 @@ static inline void sdram_selfrefresh_enable(void)
 #else
 #include <asm/arch/at91sam9_sdramc.h>
 
+#ifdef CONFIG_ARCH_AT91SAM9263
+/*
+ * FIXME either or both the SDRAM controllers (EB0, EB1) might be in use;
+ * handle those cases both here and in the Suspend-To-RAM support.
+ */
+#define        AT91_SDRAMC     AT91_SDRAMC0
+#warning Assuming EB1 SDRAM controller is *NOT* used
+#endif
+
 static u32 saved_lpr;
 
 static inline void sdram_selfrefresh_enable(void)
@@ -75,11 +84,6 @@ static inline void sdram_selfrefresh_enable(void)
 
 #define sdram_selfrefresh_disable()    at91_sys_write(AT91_SDRAMC_LPR, saved_lpr)
 
-/*
- * FIXME: The AT91SAM9263 has a second EBI controller which may have
- *        additional SDRAM.  pm_slowclock.S will require a similar fix.
- */
-
 #endif
 
 
index 4143828a9684615226e33de4fae0bbad831694fd..c6b94f60e0b2d242f3d5021bd6ed81a71c18bc7b 100644 (file)
@@ -311,11 +311,7 @@ static const struct file_operations proc_davinci_ck_operations = {
 
 static int __init davinci_ck_proc_init(void)
 {
-       struct proc_dir_entry *entry;
-
-       entry = create_proc_entry("davinci_clocks", 0, NULL);
-       if (entry)
-               entry->proc_fops = &proc_davinci_ck_operations;
+       proc_create("davinci_clocks", 0, NULL, &proc_davinci_ck_operations);
        return 0;
 
 }
index c947152f9a3c7baaf0ff5f46cd64d324eaa7298c..4877597c8758df1b1394571d7ec6a9b2b95d00e8 100644 (file)
@@ -50,8 +50,7 @@ static struct sys_timer em7210_timer = {
  */
 static struct i2c_board_info __initdata em7210_i2c_devices[] = {
        {
-               I2C_BOARD_INFO("rtc-rs5c372", 0x32),
-               .type = "rs5c372a",
+               I2C_BOARD_INFO("rs5c372a", 0x32),
        },
 };
 
index d2a7b04f1cb0764c51f7238d19385615b992bc29..d4fca75ce5426e88e23c88d5b0836fe817601c0e 100644 (file)
@@ -176,12 +176,10 @@ static struct f75375s_platform_data glantank_f75375s = {
 
 static struct i2c_board_info __initdata glantank_i2c_devices[] = {
        {
-               I2C_BOARD_INFO("rtc-rs5c372", 0x32),
-               .type = "rs5c372a",
+               I2C_BOARD_INFO("rs5c372a", 0x32),
        },
        {
                I2C_BOARD_INFO("f75375", 0x2e),
-               .type = "f75375",
                .platform_data = &glantank_f75375s,
        },
 };
index bc91d6e66bc4ea05e067d3b322b3ed8f1f64ac07..2741063bf361e34abca66f96f648c1f6a7843ea8 100644 (file)
@@ -208,12 +208,10 @@ static struct f75375s_platform_data n2100_f75375s = {
 
 static struct i2c_board_info __initdata n2100_i2c_devices[] = {
        {
-               I2C_BOARD_INFO("rtc-rs5c372", 0x32),
-               .type = "rs5c372b",
+               I2C_BOARD_INFO("rs5c372b", 0x32),
        },
        {
                I2C_BOARD_INFO("f75375", 0x2e),
-               .type = "f75375",
                .platform_data = &n2100_f75375s,
        },
 };
index 8cb07437a807f81d92eed0bbd1a7d82b5118ab5d..a51bfa6978b6a619190987d5ffb3e45a74fc5001 100644 (file)
@@ -65,7 +65,7 @@ static struct platform_device dsmg600_i2c_gpio = {
 
 static struct i2c_board_info __initdata dsmg600_i2c_board_info [] = {
        {
-               I2C_BOARD_INFO("rtc-pcf8563", 0x51),
+               I2C_BOARD_INFO("pcf8563", 0x51),
        },
 };
 
index 159e1c4f1edaa789deb76336aa1616fd38c02c1c..84b5e62a9c0ab8a6f9defe0d9c59f0c9e8f4bc6b 100644 (file)
@@ -54,7 +54,7 @@ static struct platform_device nas100d_flash = {
 
 static struct i2c_board_info __initdata nas100d_i2c_board_info [] = {
        {
-               I2C_BOARD_INFO("rtc-pcf8563", 0x51),
+               I2C_BOARD_INFO("pcf8563", 0x51),
        },
 };
 
index d9a182895a0f998bee850213b0c607dbc13eceb4..a48a6655b887ef7fe535db996f08617a8b27e9af 100644 (file)
@@ -57,7 +57,7 @@ static struct i2c_gpio_platform_data nslu2_i2c_gpio_data = {
 
 static struct i2c_board_info __initdata nslu2_i2c_board_info [] = {
        {
-               I2C_BOARD_INFO("rtc-x1205", 0x6f),
+               I2C_BOARD_INFO("x1205", 0x6f),
        },
 };
 
index 5079877200154364cf5d5d5921898909f53b2c2a..4b444fdaafea04b430234f61574471168931155f 100644 (file)
@@ -351,11 +351,9 @@ static void __init h2_init_smc91x(void)
 static struct i2c_board_info __initdata h2_i2c_board_info[] = {
        {
                I2C_BOARD_INFO("tps65010", 0x48),
-               .type           = "tps65010",
                .irq            = OMAP_GPIO_IRQ(58),
        }, {
                I2C_BOARD_INFO("isp1301_omap", 0x2d),
-               .type           = "isp1301_omap",
                .irq            = OMAP_GPIO_IRQ(2),
        },
 };
index c3ef1ee5f77bcd4a01fb9a5ecac297493c850651..7fbaa8d648cd8b8eea971c2b3168a9b1bdd204a4 100644 (file)
@@ -473,8 +473,7 @@ static struct omap_board_config_kernel h3_config[] __initdata = {
 
 static struct i2c_board_info __initdata h3_i2c_board_info[] = {
        {
-               I2C_BOARD_INFO("tps65010", 0x48),
-               .type           = "tps65013",
+               I2C_BOARD_INFO("tps65013", 0x48),
                /* .irq         = OMAP_GPIO_IRQ(??), */
        },
 };
index 4f9baba7d893e2c1b263019b868768876c78ec52..a66505f58b1591f21e25634ac16ee26bf27e043d 100644 (file)
@@ -254,7 +254,6 @@ static struct tps65010_board tps_board = {
 static struct i2c_board_info __initdata osk_i2c_board_info[] = {
        {
                I2C_BOARD_INFO("tps65010", 0x48),
-               .type           = "tps65010",
                .irq            = OMAP_GPIO_IRQ(OMAP_MPUIO(1)),
                .platform_data  = &tps_board,
 
index 6b179371e0a238b119c5f25931536549877264be..9608503d67f5475eda40eaea8efc252f5c123a9d 100644 (file)
 
 /*
  * The Orion has fully programable address map. There's a separate address
- * map for each of the device _master_ interfaces, e.g. CPU, PCI, PCIE, USB,
+ * map for each of the device _master_ interfaces, e.g. CPU, PCI, PCIe, USB,
  * Gigabit Ethernet, DMA/XOR engines, etc. Each interface has its own
  * address decode windows that allow it to access any of the Orion resources.
  *
  * CPU address decoding --
  * Linux assumes that it is the boot loader that already setup the access to
  * DDR and internal registers.
- * Setup access to PCI and PCI-E IO/MEM space is issued by this file.
+ * Setup access to PCI and PCIe IO/MEM space is issued by this file.
  * Setup access to various devices located on the device bus interface (e.g.
  * flashes, RTC, etc) should be issued by machine-setup.c according to
  * specific board population (by using orion5x_setup_*_win()).
index 439c7784af02ddfbb1c7afc10755c18f8a81e0eb..968deb58be01f7c9dd42905c486897feb5634928 100644 (file)
@@ -132,7 +132,7 @@ static struct platform_device orion5x_uart = {
 static struct resource orion5x_ehci0_resources[] = {
        {
                .start  = ORION5X_USB0_PHYS_BASE,
-               .end    = ORION5X_USB0_PHYS_BASE + SZ_4K,
+               .end    = ORION5X_USB0_PHYS_BASE + SZ_4K - 1,
                .flags  = IORESOURCE_MEM,
        },
        {
@@ -145,7 +145,7 @@ static struct resource orion5x_ehci0_resources[] = {
 static struct resource orion5x_ehci1_resources[] = {
        {
                .start  = ORION5X_USB1_PHYS_BASE,
-               .end    = ORION5X_USB1_PHYS_BASE + SZ_4K,
+               .end    = ORION5X_USB1_PHYS_BASE + SZ_4K - 1,
                .flags  = IORESOURCE_MEM,
        },
        {
@@ -317,7 +317,7 @@ struct sys_timer orion5x_timer = {
  ****************************************************************************/
 
 /*
- * Identify device ID and rev from PCIE configuration header space '0'.
+ * Identify device ID and rev from PCIe configuration header space '0'.
  */
 static void __init orion5x_id(u32 *dev, u32 *rev, char **dev_name)
 {
index f4c4c9a72a7c772ba26eb6091b553fff548d661e..14adf8d1a54ac8d96f33e23a8a92b98369faab72 100644 (file)
@@ -33,10 +33,9 @@ struct pci_sys_data;
 struct pci_bus;
 
 void orion5x_pcie_id(u32 *dev, u32 *rev);
-int orion5x_pcie_local_bus_nr(void);
-int orion5x_pci_local_bus_nr(void);
 int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys);
 struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys);
+int orion5x_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin);
 
 /*
  * Valid GPIO pins according to MPP setup, used by machine-setup.
index 872aed372327de33c6aa481bf74f753b20328ba1..44c64342dacb9cc92bdec165c930307122fc6d83 100644 (file)
@@ -241,14 +241,17 @@ void __init db88f5281_pci_preinit(void)
 
 static int __init db88f5281_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
+       int irq;
+
        /*
-        * PCIE IRQ is connected internally (not GPIO)
+        * Check for devices with hard-wired IRQs.
         */
-       if (dev->bus->number == orion5x_pcie_local_bus_nr())
-               return IRQ_ORION5X_PCIE0_INT;
+       irq = orion5x_pci_map_irq(dev, slot, pin);
+       if (irq != -1)
+               return irq;
 
        /*
-        * PCI IRQs are connected via GPIOs
+        * PCI IRQs are connected via GPIOs.
         */
        switch (slot - DB88F5281_PCI_SLOT0_OFFS) {
        case 0:
@@ -292,9 +295,7 @@ static struct mv643xx_eth_platform_data db88f5281_eth_data = {
  * RTC DS1339 on I2C bus
  ****************************************************************************/
 static struct i2c_board_info __initdata db88f5281_i2c_rtc = {
-       .driver_name    = "rtc-ds1307",
-       .type           = "ds1339",
-       .addr           = 0x68,
+       I2C_BOARD_INFO("ds1339", 0x68),
 };
 
 /*****************************************************************************
index d67790ef236e13863c20c53b8b24412a0555c2dd..f9430f5ca9a8891d01ea4a5f2ea57894af0e923e 100644 (file)
 
 static int __init dns323_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-       /* PCI-E */
-       if (dev->bus->number == orion5x_pcie_local_bus_nr())
-               return IRQ_ORION5X_PCIE0_INT;
+       int irq;
 
-       pr_err("%s: requested mapping for unknown bus\n", __func__);
+       /*
+        * Check for devices with hard-wired IRQs.
+        */
+       irq = orion5x_pci_map_irq(dev, slot, pin);
+       if (irq != -1)
+               return irq;
+
+       pr_err("%s: requested mapping for unknown device\n", __func__);
 
        return -1;
 }
@@ -220,19 +225,16 @@ static struct platform_device *dns323_plat_devices[] __initdata = {
 static struct i2c_board_info __initdata dns323_i2c_devices[] = {
        {
                I2C_BOARD_INFO("g760a", 0x3e),
-               .type = "g760a",
        },
 #if 0
        /* this entry requires the new-style driver model lm75 driver,
         * for the meantime "insmod lm75.ko force_lm75=0,0x48" is needed */
        {
-               I2C_BOARD_INFO("lm75", 0x48),
-               .type = "g751",
+               I2C_BOARD_INFO("g751", 0x48),
        },
 #endif
        {
-               I2C_BOARD_INFO("rtc-m41t80", 0x68),
-               .type = "m41t80",
+               I2C_BOARD_INFO("m41t80", 0x68),
        }
 };
 
@@ -253,9 +255,9 @@ static void __init dns323_init(void)
         */
        orion5x_setup_dev_boot_win(DNS323_NOR_BOOT_BASE, DNS323_NOR_BOOT_SIZE);
 
-       /* DNS-323 has a Marvell 88X7042 SATA controller attached via PCIE
+       /* DNS-323 has a Marvell 88X7042 SATA controller attached via PCIe
         *
-        * Open a special address decode windows for the PCIE WA.
+        * Open a special address decode windows for the PCIe WA.
         */
        orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
                                ORION5X_PCIE_WA_SIZE);
index 91413455beba0ca35f3f22d3ddad4b5d3b6f31ac..88410862feefa6d7b3c2d75b546ad80de62c485e 100644 (file)
@@ -120,13 +120,19 @@ static struct platform_device kurobox_pro_nor_flash = {
 
 static int __init kurobox_pro_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
+       int irq;
+
+       /*
+        * Check for devices with hard-wired IRQs.
+        */
+       irq = orion5x_pci_map_irq(dev, slot, pin);
+       if (irq != -1)
+               return irq;
+
        /*
         * PCI isn't used on the Kuro
         */
-       if (dev->bus->number == orion5x_pcie_local_bus_nr())
-               return IRQ_ORION5X_PCIE0_INT;
-       else
-               printk(KERN_ERR "kurobox_pro_pci_map_irq failed, unknown bus\n");
+       printk(KERN_ERR "kurobox_pro_pci_map_irq failed, unknown bus\n");
 
        return -1;
 }
@@ -162,9 +168,7 @@ static struct mv643xx_eth_platform_data kurobox_pro_eth_data = {
  * RTC 5C372a on I2C bus
  ****************************************************************************/
 static struct i2c_board_info __initdata kurobox_pro_i2c_rtc = {
-       .driver_name    = "rtc-rs5c372",
-       .type           = "rs5c372a",
-       .addr           = 0x32,
+       I2C_BOARD_INFO("rs5c372a", 0x32),
 };
 
 /*****************************************************************************
@@ -193,7 +197,7 @@ static void __init kurobox_pro_init(void)
        orion5x_setup_dev0_win(KUROBOX_PRO_NAND_BASE, KUROBOX_PRO_NAND_SIZE);
 
        /*
-        * Open a special address decode windows for the PCIE WA.
+        * Open a special address decode windows for the PCIe WA.
         */
        orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
                                ORION5X_PCIE_WA_SIZE);
index fdf99fca85b30081e1d9b5bede09ac0bd5d32d71..9d5d39fa19c36f7490ef3ad0700f2a133b4b8ccb 100644 (file)
@@ -41,11 +41,6 @@ void __init orion5x_pcie_id(u32 *dev, u32 *rev)
        *rev = orion_pcie_rev(PCIE_BASE);
 }
 
-int __init orion5x_pcie_local_bus_nr(void)
-{
-       return orion_pcie_get_local_bus_nr(PCIE_BASE);
-}
-
 static int pcie_valid_config(int bus, int dev)
 {
        /*
@@ -269,7 +264,7 @@ static int __init pcie_setup(struct pci_sys_data *sys)
  */
 static DEFINE_SPINLOCK(orion5x_pci_lock);
 
-int orion5x_pci_local_bus_nr(void)
+static int orion5x_pci_local_bus_nr(void)
 {
        u32 conf = orion5x_read(PCI_P2P_CONF);
        return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS);
@@ -557,3 +552,16 @@ struct pci_bus __init *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys
 
        return bus;
 }
+
+int __init orion5x_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       int bus = dev->bus->number;
+
+       /*
+        * PCIe endpoint?
+        */
+       if (bus < orion5x_pci_local_bus_nr())
+               return IRQ_ORION5X_PCIE0_INT;
+
+       return -1;
+}
index 37e8b2dc3ed57eaef7e601464adaad03ec6ea10d..81abc1003aaef01d01081fd7f9bc7c392bba6db5 100644 (file)
@@ -172,11 +172,14 @@ void __init rd88f5182_pci_preinit(void)
 
 static int __init rd88f5182_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
+       int irq;
+
        /*
-        * PCI-E isn't used on the RD2
+        * Check for devices with hard-wired IRQs.
         */
-       if (dev->bus->number == orion5x_pcie_local_bus_nr())
-               return IRQ_ORION5X_PCIE0_INT;
+       irq = orion5x_pci_map_irq(dev, slot, pin);
+       if (irq != -1)
+               return irq;
 
        /*
         * PCI IRQs are connected via GPIOs
@@ -224,9 +227,7 @@ static struct mv643xx_eth_platform_data rd88f5182_eth_data = {
  * RTC DS1338 on I2C bus
  ****************************************************************************/
 static struct i2c_board_info __initdata rd88f5182_i2c_rtc = {
-       .driver_name    = "rtc-ds1307",
-       .type           = "ds1338",
-       .addr           = 0x68,
+       I2C_BOARD_INFO("ds1338", 0x68),
 };
 
 /*****************************************************************************
@@ -259,7 +260,7 @@ static void __init rd88f5182_init(void)
        orion5x_setup_dev1_win(RD88F5182_NOR_BASE, RD88F5182_NOR_SIZE);
 
        /*
-        * Open a special address decode windows for the PCIE WA.
+        * Open a special address decode windows for the PCIe WA.
         */
        orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
                                ORION5X_PCIE_WA_SIZE);
index fd43863a86f6dbc0479bb22264db087a12c4ba42..9afb41ee6e078caf22f08913f05225505f820b4f 100644 (file)
@@ -141,14 +141,17 @@ void __init qnap_ts209_pci_preinit(void)
 
 static int __init qnap_ts209_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
+       int irq;
+
        /*
-        * PCIE IRQ is connected internally (not GPIO)
+        * Check for devices with hard-wired IRQs.
         */
-       if (dev->bus->number == orion5x_pcie_local_bus_nr())
-               return IRQ_ORION5X_PCIE0_INT;
+       irq = orion5x_pci_map_irq(dev, slot, pin);
+       if (irq != -1)
+               return irq;
 
        /*
-        * PCI IRQs are connected via GPIOs
+        * PCI IRQs are connected via GPIOs.
         */
        switch (slot - QNAP_TS209_PCI_SLOT0_OFFS) {
        case 0:
@@ -276,8 +279,7 @@ static void __init ts209_find_mac_addr(void)
 #define TS209_RTC_GPIO 3
 
 static struct i2c_board_info __initdata qnap_ts209_i2c_rtc = {
-       .driver_name = "rtc-s35390a",
-       .addr        = 0x30,
+       I2C_BOARD_INFO("s35390a", 0x30),
        .irq         = 0,
 };
 
@@ -373,7 +375,7 @@ static void __init qnap_ts209_init(void)
                            QNAP_TS209_NOR_BOOT_SIZE);
 
        /*
-        * Open a special address decode windows for the PCIE WA.
+        * Open a special address decode windows for the PCIe WA.
         */
        orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
                                ORION5X_PCIE_WA_SIZE);
index 7cdcb459ea9dd266d1bb9c076bb19127144ec276..6a830853aa6a610e532c33040f0ab96544dc8c3e 100644 (file)
@@ -5,9 +5,9 @@
 # Common support (must be linked before board specific support)
 obj-y                          += clock.o devices.o generic.o irq.o dma.o \
                                   time.o gpio.o
-obj-$(CONFIG_PXA25x)           += pxa25x.o mfp-pxa2xx.o
-obj-$(CONFIG_PXA27x)           += pxa27x.o mfp-pxa2xx.o
-obj-$(CONFIG_PXA3xx)           += pxa3xx.o mfp-pxa3xx.o smemc.o
+obj-$(CONFIG_PXA25x)           += mfp-pxa2xx.o pxa25x.o
+obj-$(CONFIG_PXA27x)           += mfp-pxa2xx.o pxa27x.o
+obj-$(CONFIG_PXA3xx)           += mfp-pxa3xx.o pxa3xx.o smemc.o
 obj-$(CONFIG_CPU_PXA300)       += pxa300.o
 obj-$(CONFIG_CPU_PXA320)       += pxa320.o
 
index 331f29b2d0cd5e6e2cefeeb30d92fbed9fe4969a..44617938f3f10ff044083b027077f54e0cadc21e 100644 (file)
@@ -90,11 +90,6 @@ static struct map_desc standard_io_desc[] __initdata = {
                .pfn            = __phys_to_pfn(0x40000000),
                .length         = 0x02000000,
                .type           = MT_DEVICE
-       }, {    /* LCD */
-               .virtual        =  0xf4000000,
-               .pfn            = __phys_to_pfn(0x44000000),
-               .length         = 0x00100000,
-               .type           = MT_DEVICE
        }, {    /* Mem Ctl */
                .virtual        =  0xf6000000,
                .pfn            = __phys_to_pfn(0x48000000),
index f01d18544133e435be54466468b3ead8eab08006..bdf2397540373e8d9f2047cc1cb45bb81c5a1cae 100644 (file)
@@ -40,6 +40,7 @@
 
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/pxa2xx-regs.h>
+#include <asm/arch/pxa2xx-gpio.h>
 
 #include "generic.h"
 
index 03396063b561b0c1a9ef71cc09f57d73c22a2e92..530654474bb23bda983e2909b6bbf802748d44d3 100644 (file)
@@ -301,8 +301,7 @@ static struct pxafb_mode_info tpo_tdo24mtea1_modes[] = {
 static struct pxafb_mach_info littleton_lcd_info = {
        .modes                  = tpo_tdo24mtea1_modes,
        .num_modes              = 2,
-       .lccr0                  = LCCR0_Act,
-       .lccr3                  = LCCR3_HSP | LCCR3_VSP,
+       .lcd_conn               = LCD_COLOR_TFT_16BPP,
        .pxafb_lcd_power        = littleton_lcd_power,
 };
 
index ca209c443f34c3c90fce9b8979ce04ac86702c4e..0993f4d1a0bc71bba362a86a2c92aba54f56ee4f 100644 (file)
@@ -395,8 +395,8 @@ static struct pxafb_mach_info sharp_lm8v31 = {
        .num_modes      = 1,
        .cmap_inverse   = 0,
        .cmap_static    = 0,
-       .lccr0          = LCCR0_SDS,
-       .lccr3          = LCCR3_PCP | LCCR3_Acb(255),
+       .lcd_conn       = LCD_COLOR_DSTN_16BPP | LCD_PCLK_EDGE_FALL |
+                         LCD_AC_BIAS_FREQ(255);
 };
 
 #define        MMC_POLL_RATE           msecs_to_jiffies(1000)
index d70be75bd199552d63cbc7d851d9fbd39f87d4c4..badba064dc0400326e74a3e874d9366aa6519c52 100644 (file)
@@ -114,6 +114,14 @@ static unsigned long magician_pin_config[] = {
        GPIO82_CIF_DD_5,
        GPIO84_CIF_FV,
        GPIO85_CIF_LV,
+
+       /* Magician specific input GPIOs */
+       GPIO9_GPIO,     /* unknown */
+       GPIO10_GPIO,    /* GSM_IRQ */
+       GPIO13_GPIO,    /* CPLD_IRQ */
+       GPIO107_GPIO,   /* DS1WM_IRQ */
+       GPIO108_GPIO,   /* GSM_READY */
+       GPIO115_GPIO,   /* nPEN_IRQ */
 };
 
 /*
@@ -438,7 +446,7 @@ static struct pasic3_led pasic3_leds[] = {
 
 static struct platform_device pasic3;
 
-static struct pasic3_leds_machinfo __devinit pasic3_leds_info = {
+static struct pasic3_leds_machinfo pasic3_leds_info = {
        .num_leds   = ARRAY_SIZE(pasic3_leds),
        .power_gpio = EGPIO_MAGICIAN_LED_POWER,
        .leds       = pasic3_leds,
@@ -543,9 +551,28 @@ static struct platform_device power_supply = {
 static int magician_mci_init(struct device *dev,
                                irq_handler_t detect_irq, void *data)
 {
-       return request_irq(IRQ_MAGICIAN_SD, detect_irq,
+       int err;
+
+       err = request_irq(IRQ_MAGICIAN_SD, detect_irq,
                                IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
                                "MMC card detect", data);
+       if (err)
+               goto err_request_irq;
+       err = gpio_request(EGPIO_MAGICIAN_SD_POWER, "SD_POWER");
+       if (err)
+               goto err_request_power;
+       err = gpio_request(EGPIO_MAGICIAN_nSD_READONLY, "nSD_READONLY");
+       if (err)
+               goto err_request_readonly;
+
+       return 0;
+
+err_request_readonly:
+       gpio_free(EGPIO_MAGICIAN_SD_POWER);
+err_request_power:
+       free_irq(IRQ_MAGICIAN_SD, data);
+err_request_irq:
+       return err;
 }
 
 static void magician_mci_setpower(struct device *dev, unsigned int vdd)
@@ -562,6 +589,8 @@ static int magician_mci_get_ro(struct device *dev)
 
 static void magician_mci_exit(struct device *dev, void *data)
 {
+       gpio_free(EGPIO_MAGICIAN_nSD_READONLY);
+       gpio_free(EGPIO_MAGICIAN_SD_POWER);
        free_irq(IRQ_MAGICIAN_SD, data);
 }
 
@@ -643,28 +672,42 @@ static void __init magician_init(void)
 {
        void __iomem *cpld;
        int lcd_select;
+       int err;
+
+       gpio_request(GPIO13_MAGICIAN_CPLD_IRQ, "CPLD_IRQ");
+       gpio_request(GPIO107_MAGICIAN_DS1WM_IRQ, "DS1WM_IRQ");
 
        pxa2xx_mfp_config(ARRAY_AND_SIZE(magician_pin_config));
 
        platform_add_devices(devices, ARRAY_SIZE(devices));
+
+       err = gpio_request(GPIO83_MAGICIAN_nIR_EN, "nIR_EN");
+       if (!err) {
+               gpio_direction_output(GPIO83_MAGICIAN_nIR_EN, 1);
+               pxa_set_ficp_info(&magician_ficp_info);
+       }
        pxa_set_i2c_info(NULL);
        pxa_set_mci_info(&magician_mci_info);
        pxa_set_ohci_info(&magician_ohci_info);
-       pxa_set_ficp_info(&magician_ficp_info);
 
        /* Check LCD type we have */
        cpld = ioremap_nocache(PXA_CS3_PHYS, 0x1000);
        if (cpld) {
                u8 board_id = __raw_readb(cpld+0x14);
+               iounmap(cpld);
                system_rev = board_id & 0x7;
                lcd_select = board_id & 0x8;
-               iounmap(cpld);
                pr_info("LCD type: %s\n", lcd_select ? "Samsung" : "Toppoly");
-               if (lcd_select && (system_rev < 3))
-                       pxa_gpio_mode(GPIO75_MAGICIAN_SAMSUNG_POWER_MD);
-               pxa_gpio_mode(GPIO104_MAGICIAN_LCD_POWER_1_MD);
-               pxa_gpio_mode(GPIO105_MAGICIAN_LCD_POWER_2_MD);
-               pxa_gpio_mode(GPIO106_MAGICIAN_LCD_POWER_3_MD);
+               if (lcd_select && (system_rev < 3)) {
+                       gpio_request(GPIO75_MAGICIAN_SAMSUNG_POWER, "SAMSUNG_POWER");
+                       gpio_direction_output(GPIO75_MAGICIAN_SAMSUNG_POWER, 0);
+               }
+               gpio_request(GPIO104_MAGICIAN_LCD_POWER_1, "LCD_POWER_1");
+               gpio_request(GPIO105_MAGICIAN_LCD_POWER_2, "LCD_POWER_2");
+               gpio_request(GPIO106_MAGICIAN_LCD_POWER_3, "LCD_POWER_3");
+               gpio_direction_output(GPIO104_MAGICIAN_LCD_POWER_1, 0);
+               gpio_direction_output(GPIO105_MAGICIAN_LCD_POWER_2, 0);
+               gpio_direction_output(GPIO106_MAGICIAN_LCD_POWER_3, 0);
                set_pxa_fb_info(lcd_select ? &samsung_info : &toppoly_info);
        } else
                pr_err("LCD detection: CPLD mapping failed\n");
index 18d47cfa2a188884fa48dd9886409d905c389fde..7399fb34da4e8edc3edfa72532276ca05f20005c 100644 (file)
@@ -434,8 +434,7 @@ static struct pxafb_mode_info toshiba_ltm035a776c_mode = {
 
 static struct pxafb_mach_info mainstone_pxafb_info = {
        .num_modes              = 1,
-       .lccr0                  = LCCR0_Act,
-       .lccr3                  = LCCR3_PCP,
+       .lcd_conn               = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
 };
 
 static int mainstone_mci_init(struct device *dev, irq_handler_t mstone_detect_int, void *data)
index e6be9d0aeccf2d9e94c4a1ac11306529d5f1bf2f..49d951db0f3d9dca15d2f2aeaeacc11c3b666754 100644 (file)
@@ -320,16 +320,13 @@ static struct soc_camera_link iclink[] = {
 static struct i2c_board_info __initdata pcm990_i2c_devices[] = {
        {
                /* Must initialize before the camera(s) */
-               I2C_BOARD_INFO("pca953x", 0x41),
-               .type = "pca9536",
+               I2C_BOARD_INFO("pca9536", 0x41),
                .platform_data = &pca9536_data,
        }, {
                I2C_BOARD_INFO("mt9v022", 0x48),
-               .type = "mt9v022",
                .platform_data = &iclink[0], /* With extender */
        }, {
                I2C_BOARD_INFO("mt9m001", 0x5d),
-               .type = "mt9m001",
                .platform_data = &iclink[0], /* With extender */
        },
 };
index 039194cbe477fd90eaacaa613dd87e1417040d65..ec1bbf333a3ad5a74c8c1cb06c2b0c6613fa277b 100644 (file)
@@ -46,8 +46,8 @@ int pxa_pm_enter(suspend_state_t state)
                        sleep_save_checksum += sleep_save[i];
        }
 
-       /* Clear sleep reset status */
-       RCSR = RCSR_SMR;
+       /* Clear reset status */
+       RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
 
        /* *** go zzz *** */
        pxa_cpu_pm_fns->enter(state);
index dde355e88fa1574d3760a778a4cb7bf8297d166a..b6a6f5fcc77ad56158bbd01b061c973ca4700285 100644 (file)
@@ -486,6 +486,8 @@ static int pxa3xx_set_wake(unsigned int irq, unsigned int on)
        case IRQ_MMC3:
                mask = ADXER_MFP_GEN12;
                break;
+       default:
+               return -EINVAL;
        }
 
        local_irq_save(flags);
index dbb546216be19d3220504fbce21bac09ab0780b5..4a0028087ea65740d5b253c16dc9f839ab94892a 100644 (file)
@@ -97,8 +97,7 @@ static struct pxafb_mode_info toshiba_ltm04c380k_mode = {
 
 static struct pxafb_mach_info zylonite_toshiba_lcd_info = {
        .num_modes              = 1,
-       .lccr0                  = LCCR0_Act,
-       .lccr3                  = LCCR3_PCP,
+       .lcd_conn               = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
        .pxafb_backlight_power  = zylonite_backlight_power,
 };
 
@@ -134,8 +133,7 @@ static struct pxafb_mode_info sharp_ls037_modes[] = {
 static struct pxafb_mach_info zylonite_sharp_lcd_info = {
        .modes                  = sharp_ls037_modes,
        .num_modes              = 2,
-       .lccr0                  = LCCR0_Act,
-       .lccr3                  = LCCR3_PCP | LCCR3_HSP | LCCR3_VSP,
+       .lcd_conn               = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
        .pxafb_backlight_power  = zylonite_backlight_power,
 };
 
index 1b8229d9c9d59e17890f916b79cf527a9b3a9c58..33ed048502a361b2204445e95ffc5e670dd8f645 100644 (file)
@@ -372,7 +372,7 @@ config CPU_FEROCEON
        select CPU_PABRT_NOIFAR
        select CPU_CACHE_VIVT
        select CPU_CP15_MMU
-       select CPU_COPY_V4WB if MMU
+       select CPU_COPY_FEROCEON if MMU
        select CPU_TLB_V4WBI if MMU
 
 config CPU_FEROCEON_OLD_ID
@@ -523,6 +523,9 @@ config CPU_COPY_V4WT
 config CPU_COPY_V4WB
        bool
 
+config CPU_COPY_FEROCEON
+       bool
+
 config CPU_COPY_V6
        bool
 
@@ -658,7 +661,7 @@ config CPU_DCACHE_SIZE
 
 config CPU_DCACHE_WRITETHROUGH
        bool "Force write through D-cache"
-       depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_FEROCEON) && !CPU_DCACHE_DISABLE
+       depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020) && !CPU_DCACHE_DISABLE
        default y if CPU_ARM925T
        help
          Say Y here to use the data cache in writethrough mode. Unless you
index 44536a0b995a5b2d1ec129c133ac1463a466fdd6..32b2d2d213a62e1913fd80bacb2c80b1565d32e7 100644 (file)
@@ -36,6 +36,7 @@ obj-$(CONFIG_CPU_CACHE_V7)    += cache-v7.o
 obj-$(CONFIG_CPU_COPY_V3)      += copypage-v3.o
 obj-$(CONFIG_CPU_COPY_V4WT)    += copypage-v4wt.o
 obj-$(CONFIG_CPU_COPY_V4WB)    += copypage-v4wb.o
+obj-$(CONFIG_CPU_COPY_FEROCEON)        += copypage-feroceon.o
 obj-$(CONFIG_CPU_COPY_V6)      += copypage-v6.o context.o
 obj-$(CONFIG_CPU_SA1100)       += copypage-v4mc.o
 obj-$(CONFIG_CPU_XSCALE)       += copypage-xscale.o
diff --git a/arch/arm/mm/copypage-feroceon.S b/arch/arm/mm/copypage-feroceon.S
new file mode 100644 (file)
index 0000000..7eb0d32
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ *  linux/arch/arm/lib/copypage-feroceon.S
+ *
+ *  Copyright (C) 2008 Marvell Semiconductors
+ *
+ * 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.
+ *
+ * This handles copy_user_page and clear_user_page on Feroceon
+ * more optimally than the generic implementations.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/asm-offsets.h>
+
+       .text
+       .align  5
+
+ENTRY(feroceon_copy_user_page)
+       stmfd   sp!, {r4-r9, lr}
+       mov     ip, #PAGE_SZ
+1:     mov     lr, r1
+       ldmia   r1!, {r2 - r9}
+       pld     [lr, #32]
+       pld     [lr, #64]
+       pld     [lr, #96]
+       pld     [lr, #128]
+       pld     [lr, #160]
+       pld     [lr, #192]
+       pld     [lr, #224]
+       stmia   r0, {r2 - r9}
+       ldmia   r1!, {r2 - r9}
+       mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D line
+       add     r0, r0, #32
+       stmia   r0, {r2 - r9}
+       ldmia   r1!, {r2 - r9}
+       mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D line
+       add     r0, r0, #32
+       stmia   r0, {r2 - r9}
+       ldmia   r1!, {r2 - r9}
+       mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D line
+       add     r0, r0, #32
+       stmia   r0, {r2 - r9}
+       ldmia   r1!, {r2 - r9}
+       mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D line
+       add     r0, r0, #32
+       stmia   r0, {r2 - r9}
+       ldmia   r1!, {r2 - r9}
+       mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D line
+       add     r0, r0, #32
+       stmia   r0, {r2 - r9}
+       ldmia   r1!, {r2 - r9}
+       mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D line
+       add     r0, r0, #32
+       stmia   r0, {r2 - r9}
+       ldmia   r1!, {r2 - r9}
+       mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D line
+       add     r0, r0, #32
+       stmia   r0, {r2 - r9}
+       subs    ip, ip, #(32 * 8)
+       mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D line
+       add     r0, r0, #32
+       bne     1b
+       mcr     p15, 0, ip, c7, c10, 4          @ drain WB
+       ldmfd   sp!, {r4-r9, pc}
+
+       .align  5
+
+ENTRY(feroceon_clear_user_page)
+       stmfd   sp!, {r4-r7, lr}
+       mov     r1, #PAGE_SZ/32
+       mov     r2, #0
+       mov     r3, #0
+       mov     r4, #0
+       mov     r5, #0
+       mov     r6, #0
+       mov     r7, #0
+       mov     ip, #0
+       mov     lr, #0
+1:     stmia   r0, {r2-r7, ip, lr}
+       subs    r1, r1, #1
+       mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D line
+       add     r0, r0, #32
+       bne     1b
+       mcr     p15, 0, r1, c7, c10, 4          @ drain WB
+       ldmfd   sp!, {r4-r7, pc}
+
+       __INITDATA
+
+       .type   feroceon_user_fns, #object
+ENTRY(feroceon_user_fns)
+       .long   feroceon_clear_user_page
+       .long   feroceon_copy_user_page
+       .size   feroceon_user_fns, . - feroceon_user_fns
index 62066f3020c801353e3ea281d2ac57879e3e076c..7429f8c01015ffaff33372c67057f78aeba25e1d 100644 (file)
@@ -26,8 +26,8 @@ EXPORT_SYMBOL(ioport_unmap);
 #ifdef CONFIG_PCI
 void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
 {
-       unsigned long start = pci_resource_start(dev, bar);
-       unsigned long len   = pci_resource_len(dev, bar);
+       resource_size_t start = pci_resource_start(dev, bar);
+       resource_size_t len   = pci_resource_len(dev, bar);
        unsigned long flags = pci_resource_flags(dev, bar);
 
        if (!len || !start)
index d41a75ed3dce27431fd11c78f7cf27553bbbe61c..2d6d682c206a814e5b7c41d7e8ce851f68721b18 100644 (file)
@@ -35,6 +35,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
  * zero-initialized data and COW.
  */
 struct page *empty_zero_page;
+EXPORT_SYMBOL(empty_zero_page);
 
 /*
  * The pmd table for the upper-most set of pages.
index 90e7594e29b182123f1831d329418bd16228909a..a02c1712b52de690d0410bf3ce3fe2a5a90a131c 100644 (file)
@@ -93,7 +93,7 @@ ENTRY(cpu_feroceon_reset)
  *
  * Called with IRQs disabled
  */
-       .align  10
+       .align  5
 ENTRY(cpu_feroceon_do_idle)
        mov     r0, #0
        mcr     p15, 0, r0, c7, c10, 4          @ Drain write buffer
@@ -106,6 +106,7 @@ ENTRY(cpu_feroceon_do_idle)
  *     Clean and invalidate all cache entries in a particular
  *     address space.
  */
+       .align  5
 ENTRY(feroceon_flush_user_cache_all)
        /* FALLTHROUGH */
 
@@ -118,12 +119,8 @@ ENTRY(feroceon_flush_kern_cache_all)
        mov     r2, #VM_EXEC
        mov     ip, #0
 __flush_whole_cache:
-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-       mcr     p15, 0, ip, c7, c6, 0           @ invalidate D cache
-#else
 1:     mrc     p15, 0, r15, c7, c14, 3         @ test,clean,invalidate
        bne     1b
-#endif
        tst     r2, #VM_EXEC
        mcrne   p15, 0, ip, c7, c5, 0           @ invalidate I cache
        mcrne   p15, 0, ip, c7, c10, 4          @ drain WB
@@ -139,27 +136,19 @@ __flush_whole_cache:
  *     - end   - end address (exclusive)
  *     - flags - vm_flags describing address space
  */
+       .align  5
 ENTRY(feroceon_flush_user_cache_range)
        mov     ip, #0
        sub     r3, r1, r0                      @ calculate total size
        cmp     r3, #CACHE_DLIMIT
        bgt     __flush_whole_cache
 1:     tst     r2, #VM_EXEC
-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-       mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
-       mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
-       add     r0, r0, #CACHE_DLINESIZE
-       mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
-       mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
-       add     r0, r0, #CACHE_DLINESIZE
-#else
        mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
        mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
        add     r0, r0, #CACHE_DLINESIZE
        mcr     p15, 0, r0, c7, c14, 1          @ clean and invalidate D entry
        mcrne   p15, 0, r0, c7, c5, 1           @ invalidate I entry
        add     r0, r0, #CACHE_DLINESIZE
-#endif
        cmp     r0, r1
        blo     1b
        tst     r2, #VM_EXEC
@@ -176,6 +165,7 @@ ENTRY(feroceon_flush_user_cache_range)
  *     - start - virtual start address
  *     - end   - virtual end address
  */
+       .align  5
 ENTRY(feroceon_coherent_kern_range)
        /* FALLTHROUGH */
 
@@ -207,6 +197,7 @@ ENTRY(feroceon_coherent_user_range)
  *
  *     - addr  - page aligned address
  */
+       .align  5
 ENTRY(feroceon_flush_kern_dcache_page)
        add     r1, r0, #PAGE_SZ
 1:     mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
@@ -231,13 +222,12 @@ ENTRY(feroceon_flush_kern_dcache_page)
  *
  * (same as v4wb)
  */
+       .align  5
 ENTRY(feroceon_dma_inv_range)
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
        tst     r0, #CACHE_DLINESIZE - 1
        mcrne   p15, 0, r0, c7, c10, 1          @ clean D entry
        tst     r1, #CACHE_DLINESIZE - 1
        mcrne   p15, 0, r1, c7, c10, 1          @ clean D entry
-#endif
        bic     r0, r0, #CACHE_DLINESIZE - 1
 1:     mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry
        add     r0, r0, #CACHE_DLINESIZE
@@ -256,14 +246,13 @@ ENTRY(feroceon_dma_inv_range)
  *
  * (same as v4wb)
  */
+       .align  5
 ENTRY(feroceon_dma_clean_range)
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
        bic     r0, r0, #CACHE_DLINESIZE - 1
 1:     mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
        add     r0, r0, #CACHE_DLINESIZE
        cmp     r0, r1
        blo     1b
-#endif
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
        mov     pc, lr
 
@@ -275,14 +264,10 @@ ENTRY(feroceon_dma_clean_range)
  *     - start - virtual start address
  *     - end   - virtual end address
  */
+       .align  5
 ENTRY(feroceon_dma_flush_range)
        bic     r0, r0, #CACHE_DLINESIZE - 1
-1:
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
-       mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
-#else
-       mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
-#endif
+1:     mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry
        add     r0, r0, #CACHE_DLINESIZE
        cmp     r0, r1
        blo     1b
@@ -300,13 +285,12 @@ ENTRY(feroceon_cache_fns)
        .long   feroceon_dma_clean_range
        .long   feroceon_dma_flush_range
 
+       .align  5
 ENTRY(cpu_feroceon_dcache_clean_area)
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 1:     mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
        add     r0, r0, #CACHE_DLINESIZE
        subs    r1, r1, #CACHE_DLINESIZE
        bhi     1b
-#endif
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
        mov     pc, lr
 
@@ -323,13 +307,9 @@ ENTRY(cpu_feroceon_dcache_clean_area)
 ENTRY(cpu_feroceon_switch_mm)
 #ifdef CONFIG_MMU
        mov     ip, #0
-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-       mcr     p15, 0, ip, c7, c6, 0           @ invalidate D cache
-#else
 @ && 'Clean & Invalidate whole DCache'
 1:     mrc     p15, 0, r15, c7, c14, 3         @ test,clean,invalidate
        bne     1b
-#endif
        mcr     p15, 0, ip, c7, c5, 0           @ invalidate I cache
        mcr     p15, 0, ip, c7, c10, 4          @ drain WB
        mcr     p15, 0, r0, c2, c0, 0           @ load page table pointer
@@ -362,16 +342,9 @@ ENTRY(cpu_feroceon_set_pte_ext)
        tst     r1, #L_PTE_PRESENT | L_PTE_YOUNG        @ Present and Young?
        movne   r2, #0
 
-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-       eor     r3, r2, #0x0a                   @ C & small page?
-       tst     r3, #0x0b
-       biceq   r2, r2, #4
-#endif
        str     r2, [r0]                        @ hardware version
        mov     r0, r0
-#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
        mcr     p15, 0, r0, c7, c10, 1          @ clean D entry
-#endif
        mcr     p15, 0, r0, c7, c10, 4          @ drain WB
 #endif
        mov     pc, lr
@@ -387,20 +360,11 @@ __feroceon_setup:
        mcr     p15, 0, r0, c8, c7              @ invalidate I,D TLBs on v4
 #endif
 
-
-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-       mov     r0, #4                          @ disable write-back on caches explicitly
-       mcr     p15, 7, r0, c15, c0, 0
-#endif
-
        adr     r5, feroceon_crval
        ldmia   r5, {r5, r6}
        mrc     p15, 0, r0, c1, c0              @ get control register v4
        bic     r0, r0, r5
        orr     r0, r0, r6
-#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
-       orr     r0, r0, #0x4000                 @ .1.. .... .... ....
-#endif
        mov     pc, lr
        .size   __feroceon_setup, . - __feroceon_setup
 
@@ -476,7 +440,7 @@ __feroceon_old_id_proc_info:
        .long   cpu_feroceon_name
        .long   feroceon_processor_functions
        .long   v4wbi_tlb_fns
-       .long   v4wb_user_fns
+       .long   feroceon_user_fns
        .long   feroceon_cache_fns
        .size   __feroceon_old_id_proc_info, . - __feroceon_old_id_proc_info
 #endif
@@ -502,6 +466,6 @@ __feroceon_proc_info:
        .long   cpu_feroceon_name
        .long   feroceon_processor_functions
        .long   v4wbi_tlb_fns
-       .long   v4wb_user_fns
+       .long   feroceon_user_fns
        .long   feroceon_cache_fns
        .size   __feroceon_proc_info, . - __feroceon_proc_info
index 75bae067922d1c55fdef728f67e8f952062009be..74fae6045650409bdd4dc44a343d60887b540443 100644 (file)
@@ -51,7 +51,7 @@
 /*
  * MPCore SCU event monitor support
  */
-#define SCU_EVENTMONITORS_VA_BASE __io_address(REALVIEW_MPCORE_SCU_BASE + 0x10)
+#define SCU_EVENTMONITORS_VA_BASE __io_address(REALVIEW_EB11MP_SCU_BASE + 0x10)
 
 /*
  * Bitmask of used SCU counters
@@ -80,7 +80,7 @@ static irqreturn_t scu_em_interrupt(int irq, void *arg)
        struct eventmonitor __iomem *emc = SCU_EVENTMONITORS_VA_BASE;
        unsigned int cnt;
 
-       cnt = irq - IRQ_PMU_SCU0;
+       cnt = irq - IRQ_EB11MP_PMU_SCU0;
        oprofile_add_sample(get_irq_regs(), SCU_COUNTER(cnt));
        scu_reset_counter(emc, cnt);
 
@@ -119,10 +119,10 @@ static int scu_start(void)
         */
        for (i = 0; i < NUM_SCU_COUNTERS; i++) {
                if (scu_em_used & (1 << i)) {
-                       ret = request_irq(IRQ_PMU_SCU0 + i, scu_em_interrupt, IRQF_DISABLED, "SCU PMU", NULL);
+                       ret = request_irq(IRQ_EB11MP_PMU_SCU0 + i, scu_em_interrupt, IRQF_DISABLED, "SCU PMU", NULL);
                        if (ret) {
                                printk(KERN_ERR "oprofile: unable to request IRQ%u for SCU Event Monitor\n",
-                                      IRQ_PMU_SCU0 + i);
+                                      IRQ_EB11MP_PMU_SCU0 + i);
                                goto err_free_scu;
                        }
                }
@@ -153,7 +153,7 @@ static int scu_start(void)
 
  err_free_scu:
        while (i--)
-               free_irq(IRQ_PMU_SCU0 + i, NULL);
+               free_irq(IRQ_EB11MP_PMU_SCU0 + i, NULL);
        return ret;
 }
 
@@ -175,7 +175,7 @@ static void scu_stop(void)
        for (i = 0; i < NUM_SCU_COUNTERS; i++) {
                if (scu_em_used & (1 << i)) {
                        scu_reset_counter(emc, i);
-                       free_irq(IRQ_PMU_SCU0 + i, NULL);
+                       free_irq(IRQ_EB11MP_PMU_SCU0 + i, NULL);
                }
        }
 }
@@ -225,10 +225,10 @@ static int em_setup_ctrs(void)
 }
 
 static int arm11_irqs[] = {
-       [0]     = IRQ_PMU_CPU0,
-       [1]     = IRQ_PMU_CPU1,
-       [2]     = IRQ_PMU_CPU2,
-       [3]     = IRQ_PMU_CPU3
+       [0]     = IRQ_EB11MP_PMU_CPU0,
+       [1]     = IRQ_EB11MP_PMU_CPU1,
+       [2]     = IRQ_EB11MP_PMU_CPU2,
+       [3]     = IRQ_EB11MP_PMU_CPU3
 };
 
 static int em_start(void)
@@ -273,22 +273,22 @@ static int em_setup(void)
        /*
         * Send SCU PMU interrupts to the "owner" CPU.
         */
-       em_route_irq(IRQ_PMU_SCU0, 0);
-       em_route_irq(IRQ_PMU_SCU1, 0);
-       em_route_irq(IRQ_PMU_SCU2, 1);
-       em_route_irq(IRQ_PMU_SCU3, 1);
-       em_route_irq(IRQ_PMU_SCU4, 2);
-       em_route_irq(IRQ_PMU_SCU5, 2);
-       em_route_irq(IRQ_PMU_SCU6, 3);
-       em_route_irq(IRQ_PMU_SCU7, 3);
+       em_route_irq(IRQ_EB11MP_PMU_SCU0, 0);
+       em_route_irq(IRQ_EB11MP_PMU_SCU1, 0);
+       em_route_irq(IRQ_EB11MP_PMU_SCU2, 1);
+       em_route_irq(IRQ_EB11MP_PMU_SCU3, 1);
+       em_route_irq(IRQ_EB11MP_PMU_SCU4, 2);
+       em_route_irq(IRQ_EB11MP_PMU_SCU5, 2);
+       em_route_irq(IRQ_EB11MP_PMU_SCU6, 3);
+       em_route_irq(IRQ_EB11MP_PMU_SCU7, 3);
 
        /*
         * Send CP15 PMU interrupts to the owner CPU.
         */
-       em_route_irq(IRQ_PMU_CPU0, 0);
-       em_route_irq(IRQ_PMU_CPU1, 1);
-       em_route_irq(IRQ_PMU_CPU2, 2);
-       em_route_irq(IRQ_PMU_CPU3, 3);
+       em_route_irq(IRQ_EB11MP_PMU_CPU0, 0);
+       em_route_irq(IRQ_EB11MP_PMU_CPU1, 1);
+       em_route_irq(IRQ_EB11MP_PMU_CPU2, 2);
+       em_route_irq(IRQ_EB11MP_PMU_CPU3, 3);
 
        return 0;
 }
index 078cd33f467be29256d3d81f39da48c9df6fb510..e4796c67a831aa930208c736de6722b1a460891b 100644 (file)
@@ -5,14 +5,7 @@
  */
 
 #include <linux/thread_info.h>
-
-#define DEFINE(sym, val) \
-        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : : )
-
-#define OFFSET(sym, str, mem) \
-        DEFINE(sym, offsetof(struct str, mem));
+#include <linux/kbuild.h>
 
 void foo(void)
 {
index b835257a8fa39d88d794ad2667ef9f46a4e6028c..cd12edbea9f26c403bdc5a3c85f034e76766fc9a 100644 (file)
@@ -369,11 +369,7 @@ static const struct file_operations proc_tlb_operations = {
 
 static int __init proctlb_init(void)
 {
-       struct proc_dir_entry *entry;
-
-       entry = create_proc_entry("tlb", 0, NULL);
-       if (entry)
-               entry->proc_fops = &proc_tlb_operations;
+       proc_create("tlb", 0, NULL, &proc_tlb_operations);
        return 0;
 }
 late_initcall(proctlb_init);
index b56b2741cdea6746c0a445408c5d40f40786fec5..721f15f3cebf1915d67f2b83ab46574697517155 100644 (file)
@@ -34,8 +34,7 @@
 #include <linux/hardirq.h>
 #include <linux/irq.h>
 #include <linux/thread_info.h>
-
-#define DEFINE(sym, val) asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+#include <linux/kbuild.h>
 
 int main(void)
 {
index d1fa24401dc6995d92410efb3948989049682e52..cb9d883d493c4b3ad30dbefed9766de9980faf0e 100644 (file)
@@ -212,7 +212,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
 
        /* Set up registers for signal handler */
        wrusp((unsigned long)frame);
-       if (get_personality & FDPIC_FUNCPTRS) {
+       if (current->personality & FDPIC_FUNCPTRS) {
                struct fdpic_func_descriptor __user *funcptr =
                        (struct fdpic_func_descriptor *) ka->sa.sa_handler;
                __get_user(regs->pc, &funcptr->text);
index fddce32901a2249e31af17a17bacb3afa768667d..024f418ae5430b36951c67072ac312e5c139c58c 100644 (file)
@@ -499,20 +499,17 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
 #if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
        {
                I2C_BOARD_INFO("ad7142_joystick", 0x2C),
-               .type = "ad7142_joystick",
                .irq = 39,
        },
 #endif
 #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_lcd", 0x22),
-               .type = "pcf8574_lcd",
        },
 #endif
 #if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_keypad", 0x27),
-               .type = "pcf8574_keypad",
                .irq = 39,
        },
 #endif
index 0cec14b1ef5c0ee45345dcdcd05303e30857e9ea..d3727b7c2d7d94da933ec76834c2a2378764b407 100644 (file)
@@ -751,20 +751,17 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
 #if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
        {
                I2C_BOARD_INFO("ad7142_joystick", 0x2C),
-               .type = "ad7142_joystick",
                .irq = 55,
        },
 #endif
 #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_lcd", 0x22),
-               .type = "pcf8574_lcd",
        },
 #endif
 #if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_keypad", 0x27),
-               .type = "pcf8574_keypad",
                .irq = 72,
        },
 #endif
index 231dfbd3bc1ffcefc1a9c11b94ad885ab1d376d3..b00f68ac6bc991e972a765fe670bfff67bcc5ea8 100644 (file)
@@ -641,13 +641,11 @@ static struct i2c_board_info __initdata bfin_i2c_board_info1[] = {
 #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_lcd", 0x22),
-               .type = "pcf8574_lcd",
        },
 #endif
 #if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_keypad", 0x27),
-               .type = "pcf8574_keypad",
                .irq = 212,
        },
 #endif
index aad0a9e5991a3e358685726cb5fed98afa4de8ed..44f7b4f794760dcaebf8cae38f114a39739e4d6f 100644 (file)
@@ -75,9 +75,9 @@ __init init_cris_profile(void)
 
        sample_buffer_pos = sample_buffer;
 
-       entry = create_proc_entry("system_profile", S_IWUSR | S_IRUGO, NULL);
+       entry = proc_create("system_profile", S_IWUSR | S_IRUGO, NULL,
+                           &cris_proc_profile_operations);
        if (entry) {
-               entry->proc_fops = &cris_proc_profile_operations;
                entry->size = SAMPLE_BUFFER_SIZE;
        }
        prof_running = 1;
index fbb19fc1af407e83fc3d52e7422a7b370eb25f5c..9de96843a27808d0f98e0221057f6d2b53a02f06 100644 (file)
@@ -7,15 +7,13 @@
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/personality.h>
+#include <linux/kbuild.h>
 #include <asm/registers.h>
 #include <asm/ucontext.h>
 #include <asm/processor.h>
 #include <asm/thread_info.h>
 #include <asm/gdb-stub.h>
 
-#define DEFINE(sym, val) \
-        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
 #define DEF_PTREG(sym, reg) \
         asm volatile("\n->" #sym " %0 offsetof(struct pt_regs, " #reg ")" \
                     : : "i" (offsetof(struct pt_regs, reg)))
         asm volatile("\n->" #sym " %0 offsetof(struct frv_frame0, " #reg ")" \
                     : : "i" (offsetof(struct frv_frame0, reg)))
 
-#define BLANK() asm volatile("\n->" : : )
-
-#define OFFSET(sym, str, mem) \
-       DEFINE(sym, offsetof(struct str, mem));
-
 void foo(void)
 {
        /* offsets into the thread_info structure */
index d64bcaff54cd441ebd76c735c9ad878109c76223..3bdb368292a8c8a53f9c00b3aa39dc169420b095 100644 (file)
@@ -297,7 +297,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
        __frame->lr   = (unsigned long) &frame->retcode;
        __frame->gr8  = sig;
 
-       if (get_personality & FDPIC_FUNCPTRS) {
+       if (current->personality & FDPIC_FUNCPTRS) {
                struct fdpic_func_descriptor __user *funcptr =
                        (struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
                __get_user(__frame->pc, &funcptr->text);
@@ -396,7 +396,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        __frame->gr8 = sig;
        __frame->gr9 = (unsigned long) &frame->info;
 
-       if (get_personality & FDPIC_FUNCPTRS) {
+       if (current->personality & FDPIC_FUNCPTRS) {
                struct fdpic_func_descriptor __user *funcptr =
                        (struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
                __get_user(__frame->pc, &funcptr->text);
index a40df80b2ebd0f862166fcb1eecb4afdc09929fd..1d2dfe67d4426b7805e595f75293b5b46e5f6a8f 100644 (file)
@@ -362,11 +362,8 @@ asmlinkage void memory_access_exception(unsigned long esr0,
 #ifdef CONFIG_MMU
        unsigned long fixup;
 
-       if ((esr0 & ESRx_EC) == ESRx_EC_DATA_ACCESS)
-               if (handle_misalignment(esr0, ear0, epcr0) == 0)
-                       return;
-
-       if ((fixup = search_exception_table(__frame->pc)) != 0) {
+       fixup = search_exception_table(__frame->pc);
+       if (fixup) {
                __frame->pc = fixup;
                return;
        }
index 068fa04bd52752764b4d6d3838609d7b64042f45..35f6df28351ec103b59570f01e79dd66b49167d5 100644 (file)
@@ -13,8 +13,8 @@
 
 void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
 {
-       unsigned long start = pci_resource_start(dev, bar);
-       unsigned long len = pci_resource_len(dev, bar);
+       resource_size_t start = pci_resource_start(dev, bar);
+       resource_size_t len = pci_resource_len(dev, bar);
        unsigned long flags = pci_resource_flags(dev, bar);
 
        if (!len || !start)
diff --git a/arch/frv/mm/unaligned.c b/arch/frv/mm/unaligned.c
deleted file mode 100644 (file)
index 8f0375f..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-/* unaligned.c: unalignment fixup handler for CPUs on which it is supported (FR451 only)
- *
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.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/sched.h>
-#include <linux/signal.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/types.h>
-#include <linux/user.h>
-#include <linux/string.h>
-#include <linux/linkage.h>
-#include <linux/init.h>
-
-#include <asm/setup.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-#if 0
-#define kdebug(fmt, ...) printk("FDPIC "fmt"\n" ,##__VA_ARGS__ )
-#else
-#define kdebug(fmt, ...) do {} while(0)
-#endif
-
-#define _MA_SIGNED     0x01
-#define _MA_HALF       0x02
-#define _MA_WORD       0x04
-#define _MA_DWORD      0x08
-#define _MA_SZ_MASK    0x0e
-#define _MA_LOAD       0x10
-#define _MA_STORE      0x20
-#define _MA_UPDATE     0x40
-#define _MA_IMM                0x80
-
-#define _MA_LDxU       _MA_LOAD | _MA_UPDATE
-#define _MA_LDxI       _MA_LOAD | _MA_IMM
-#define _MA_STxU       _MA_STORE | _MA_UPDATE
-#define _MA_STxI       _MA_STORE | _MA_IMM
-
-static const uint8_t tbl_LDGRk_reg[0x40] = {
-       [0x02] = _MA_LOAD | _MA_HALF | _MA_SIGNED,      /* LDSH  @(GRi,GRj),GRk */
-       [0x03] = _MA_LOAD | _MA_HALF,                   /* LDUH  @(GRi,GRj),GRk */
-       [0x04] = _MA_LOAD | _MA_WORD,                   /* LD    @(GRi,GRj),GRk */
-       [0x05] = _MA_LOAD | _MA_DWORD,                  /* LDD   @(GRi,GRj),GRk */
-       [0x12] = _MA_LDxU | _MA_HALF | _MA_SIGNED,      /* LDSHU @(GRi,GRj),GRk */
-       [0x13] = _MA_LDxU | _MA_HALF,                   /* LDUHU @(GRi,GRj),GRk */
-       [0x14] = _MA_LDxU | _MA_WORD,                   /* LDU   @(GRi,GRj),GRk */
-       [0x15] = _MA_LDxU | _MA_DWORD,                  /* LDDU  @(GRi,GRj),GRk */
-};
-
-static const uint8_t tbl_STGRk_reg[0x40] = {
-       [0x01] = _MA_STORE | _MA_HALF,                  /* STH   @(GRi,GRj),GRk */
-       [0x02] = _MA_STORE | _MA_WORD,                  /* ST    @(GRi,GRj),GRk */
-       [0x03] = _MA_STORE | _MA_DWORD,                 /* STD   @(GRi,GRj),GRk */
-       [0x11] = _MA_STxU  | _MA_HALF,                  /* STHU  @(GRi,GRj),GRk */
-       [0x12] = _MA_STxU  | _MA_WORD,                  /* STU   @(GRi,GRj),GRk */
-       [0x13] = _MA_STxU  | _MA_DWORD,                 /* STDU  @(GRi,GRj),GRk */
-};
-
-static const uint8_t tbl_LDSTGRk_imm[0x80] = {
-       [0x31] = _MA_LDxI | _MA_HALF | _MA_SIGNED,      /* LDSHI @(GRi,d12),GRk */
-       [0x32] = _MA_LDxI | _MA_WORD,                   /* LDI   @(GRi,d12),GRk */
-       [0x33] = _MA_LDxI | _MA_DWORD,                  /* LDDI  @(GRi,d12),GRk */
-       [0x36] = _MA_LDxI | _MA_HALF,                   /* LDUHI @(GRi,d12),GRk */
-       [0x51] = _MA_STxI | _MA_HALF,                   /* STHI  @(GRi,d12),GRk */
-       [0x52] = _MA_STxI | _MA_WORD,                   /* STI   @(GRi,d12),GRk */
-       [0x53] = _MA_STxI | _MA_DWORD,                  /* STDI  @(GRi,d12),GRk */
-};
-
-
-/*****************************************************************************/
-/*
- * see if we can handle the exception by fixing up a misaligned memory access
- */
-int handle_misalignment(unsigned long esr0, unsigned long ear0, unsigned long epcr0)
-{
-       unsigned long insn, addr, *greg;
-       int GRi, GRj, GRk, D12, op;
-
-       union {
-               uint64_t _64;
-               uint32_t _32[2];
-               uint16_t _16;
-               uint8_t _8[8];
-       } x;
-
-       if (!(esr0 & ESR0_EAV) || !(epcr0 & EPCR0_V) || !(ear0 & 7))
-               return -EAGAIN;
-
-       epcr0 &= EPCR0_PC;
-
-       if (__frame->pc != epcr0) {
-               kdebug("MISALIGN: Execution not halted on excepting instruction\n");
-               BUG();
-       }
-
-       if (__get_user(insn, (unsigned long *) epcr0) < 0)
-               return -EFAULT;
-
-       /* determine the instruction type first */
-       switch ((insn >> 18) & 0x7f) {
-       case 0x2:
-               /* LDx @(GRi,GRj),GRk */
-               op = tbl_LDGRk_reg[(insn >> 6) & 0x3f];
-               break;
-
-       case 0x3:
-               /* STx GRk,@(GRi,GRj) */
-               op = tbl_STGRk_reg[(insn >> 6) & 0x3f];
-               break;
-
-       default:
-               op = tbl_LDSTGRk_imm[(insn >> 18) & 0x7f];
-               break;
-       }
-
-       if (!op)
-               return -EAGAIN;
-
-       kdebug("MISALIGN: pc=%08lx insn=%08lx ad=%08lx op=%02x\n", epcr0, insn, ear0, op);
-
-       memset(&x, 0xba, 8);
-
-       /* validate the instruction parameters */
-       greg = (unsigned long *) &__frame->tbr;
-
-       GRi = (insn >> 12) & 0x3f;
-       GRk = (insn >> 25) & 0x3f;
-
-       if (GRi > 31 || GRk > 31)
-               return -ENOENT;
-
-       if (op & _MA_DWORD && GRk & 1)
-               return -EINVAL;
-
-       if (op & _MA_IMM) {
-               D12 = insn & 0xfff;
-               asm ("slli %0,#20,%0 ! srai %0,#20,%0" : "=r"(D12) : "0"(D12)); /* sign extend */
-               addr = (GRi ? greg[GRi] : 0) + D12;
-       }
-       else {
-               GRj = (insn >>  0) & 0x3f;
-               if (GRj > 31)
-                       return -ENOENT;
-               addr = (GRi ? greg[GRi] : 0) + (GRj ? greg[GRj] : 0);
-       }
-
-       if (addr != ear0) {
-               kdebug("MISALIGN: Calculated addr (%08lx) does not match EAR0 (%08lx)\n",
-                      addr, ear0);
-               return -EFAULT;
-       }
-
-       /* check the address is okay */
-       if (user_mode(__frame) && ___range_ok(ear0, 8) < 0)
-               return -EFAULT;
-
-       /* perform the memory op */
-       if (op & _MA_STORE) {
-               /* perform a store */
-               x._32[0] = 0;
-               if (GRk != 0) {
-                       if (op & _MA_HALF) {
-                               x._16 = greg[GRk];
-                       }
-                       else {
-                               x._32[0] = greg[GRk];
-                       }
-               }
-               if (op & _MA_DWORD)
-                       x._32[1] = greg[GRk + 1];
-
-               kdebug("MISALIGN: Store GR%d { %08x:%08x } -> %08lx (%dB)\n",
-                      GRk, x._32[1], x._32[0], addr, op & _MA_SZ_MASK);
-
-               if (__memcpy_user((void *) addr, &x, op & _MA_SZ_MASK) != 0)
-                       return -EFAULT;
-       }
-       else {
-               /* perform a load */
-               if (__memcpy_user(&x, (void *) addr, op & _MA_SZ_MASK) != 0)
-                       return -EFAULT;
-
-               if (op & _MA_HALF) {
-                       if (op & _MA_SIGNED)
-                               asm ("slli %0,#16,%0 ! srai %0,#16,%0"
-                                    : "=r"(x._32[0]) : "0"(x._16));
-                       else
-                               asm ("sethi #0,%0"
-                                    : "=r"(x._32[0]) : "0"(x._16));
-               }
-
-               kdebug("MISALIGN: Load %08lx (%dB) -> GR%d, { %08x:%08x }\n",
-                      addr, op & _MA_SZ_MASK, GRk, x._32[1], x._32[0]);
-
-               if (GRk != 0)
-                       greg[GRk] = x._32[0];
-               if (op & _MA_DWORD)
-                       greg[GRk + 1] = x._32[1];
-       }
-
-       /* update the base pointer if required */
-       if (op & _MA_UPDATE)
-               greg[GRi] = addr;
-
-       /* well... we've done that insn */
-       __frame->pc = __frame->pc + 4;
-
-       return 0;
-} /* end handle_misalignment() */
index fc30b4fd0914fcb607d4449b48cea1ff86772f36..2042552e08714ea60db579e3933a39227efd7018 100644 (file)
 #include <linux/kernel_stat.h>
 #include <linux/ptrace.h>
 #include <linux/hardirq.h>
+#include <linux/kbuild.h>
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
 #include <asm/ptrace.h>
 
-#define DEFINE(sym, val) \
-        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : : )
-
 int main(void)
 {
        /* offsets into the task struct */
index 3aa6c821449a90fd43d0169fb3bbcf410140602d..0df5f6f75edf7a016d7033a85519e778d4cfcc7c 100644 (file)
@@ -19,6 +19,7 @@ config IA64
        select HAVE_OPROFILE
        select HAVE_KPROBES
        select HAVE_KRETPROBES
+       select HAVE_DMA_ATTRS
        select HAVE_KVM
        default y
        help
@@ -47,6 +48,9 @@ config MMU
 config SWIOTLB
        bool
 
+config IOMMU_HELPER
+       bool
+
 config GENERIC_LOCKBREAK
        bool
        default y
@@ -615,7 +619,7 @@ config IRQ_PER_CPU
        default y
 
 config IOMMU_HELPER
-       def_bool (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC)
+       def_bool (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC || SWIOTLB)
 
 source "arch/ia64/hp/sim/Kconfig"
 
index 8f6bcfe1dadaa0fab0ec16fd2734ddf87d916450..1c44ec2a1d58e2495cb21f41759dcee218471ffc 100644 (file)
 extern int swiotlb_late_init_with_default_size (size_t size);
 extern ia64_mv_dma_alloc_coherent      swiotlb_alloc_coherent;
 extern ia64_mv_dma_free_coherent       swiotlb_free_coherent;
-extern ia64_mv_dma_map_single          swiotlb_map_single;
-extern ia64_mv_dma_unmap_single                swiotlb_unmap_single;
-extern ia64_mv_dma_map_sg              swiotlb_map_sg;
-extern ia64_mv_dma_unmap_sg            swiotlb_unmap_sg;
+extern ia64_mv_dma_map_single_attrs    swiotlb_map_single_attrs;
+extern ia64_mv_dma_unmap_single_attrs  swiotlb_unmap_single_attrs;
+extern ia64_mv_dma_map_sg_attrs                swiotlb_map_sg_attrs;
+extern ia64_mv_dma_unmap_sg_attrs      swiotlb_unmap_sg_attrs;
 extern ia64_mv_dma_supported           swiotlb_dma_supported;
 extern ia64_mv_dma_mapping_error       swiotlb_dma_mapping_error;
 
@@ -31,19 +31,19 @@ extern ia64_mv_dma_mapping_error    swiotlb_dma_mapping_error;
 
 extern ia64_mv_dma_alloc_coherent      sba_alloc_coherent;
 extern ia64_mv_dma_free_coherent       sba_free_coherent;
-extern ia64_mv_dma_map_single          sba_map_single;
-extern ia64_mv_dma_unmap_single                sba_unmap_single;
-extern ia64_mv_dma_map_sg              sba_map_sg;
-extern ia64_mv_dma_unmap_sg            sba_unmap_sg;
+extern ia64_mv_dma_map_single_attrs    sba_map_single_attrs;
+extern ia64_mv_dma_unmap_single_attrs  sba_unmap_single_attrs;
+extern ia64_mv_dma_map_sg_attrs                sba_map_sg_attrs;
+extern ia64_mv_dma_unmap_sg_attrs      sba_unmap_sg_attrs;
 extern ia64_mv_dma_supported           sba_dma_supported;
 extern ia64_mv_dma_mapping_error       sba_dma_mapping_error;
 
 #define hwiommu_alloc_coherent         sba_alloc_coherent
 #define hwiommu_free_coherent          sba_free_coherent
-#define hwiommu_map_single             sba_map_single
-#define hwiommu_unmap_single           sba_unmap_single
-#define hwiommu_map_sg                 sba_map_sg
-#define hwiommu_unmap_sg               sba_unmap_sg
+#define hwiommu_map_single_attrs       sba_map_single_attrs
+#define hwiommu_unmap_single_attrs     sba_unmap_single_attrs
+#define hwiommu_map_sg_attrs           sba_map_sg_attrs
+#define hwiommu_unmap_sg_attrs         sba_unmap_sg_attrs
 #define hwiommu_dma_supported          sba_dma_supported
 #define hwiommu_dma_mapping_error      sba_dma_mapping_error
 #define hwiommu_sync_single_for_cpu    machvec_dma_sync_single
@@ -98,41 +98,48 @@ hwsw_free_coherent (struct device *dev, size_t size, void *vaddr, dma_addr_t dma
 }
 
 dma_addr_t
-hwsw_map_single (struct device *dev, void *addr, size_t size, int dir)
+hwsw_map_single_attrs(struct device *dev, void *addr, size_t size, int dir,
+                      struct dma_attrs *attrs)
 {
        if (use_swiotlb(dev))
-               return swiotlb_map_single(dev, addr, size, dir);
+               return swiotlb_map_single_attrs(dev, addr, size, dir, attrs);
        else
-               return hwiommu_map_single(dev, addr, size, dir);
+               return hwiommu_map_single_attrs(dev, addr, size, dir, attrs);
 }
+EXPORT_SYMBOL(hwsw_map_single_attrs);
 
 void
-hwsw_unmap_single (struct device *dev, dma_addr_t iova, size_t size, int dir)
+hwsw_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size,
+                        int dir, struct dma_attrs *attrs)
 {
        if (use_swiotlb(dev))
-               return swiotlb_unmap_single(dev, iova, size, dir);
+               return swiotlb_unmap_single_attrs(dev, iova, size, dir, attrs);
        else
-               return hwiommu_unmap_single(dev, iova, size, dir);
+               return hwiommu_unmap_single_attrs(dev, iova, size, dir, attrs);
 }
-
+EXPORT_SYMBOL(hwsw_unmap_single_attrs);
 
 int
-hwsw_map_sg (struct device *dev, struct scatterlist *sglist, int nents, int dir)
+hwsw_map_sg_attrs(struct device *dev, struct scatterlist *sglist, int nents,
+                  int dir, struct dma_attrs *attrs)
 {
        if (use_swiotlb(dev))
-               return swiotlb_map_sg(dev, sglist, nents, dir);
+               return swiotlb_map_sg_attrs(dev, sglist, nents, dir, attrs);
        else
-               return hwiommu_map_sg(dev, sglist, nents, dir);
+               return hwiommu_map_sg_attrs(dev, sglist, nents, dir, attrs);
 }
+EXPORT_SYMBOL(hwsw_map_sg_attrs);
 
 void
-hwsw_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, int dir)
+hwsw_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist, int nents,
+                    int dir, struct dma_attrs *attrs)
 {
        if (use_swiotlb(dev))
-               return swiotlb_unmap_sg(dev, sglist, nents, dir);
+               return swiotlb_unmap_sg_attrs(dev, sglist, nents, dir, attrs);
        else
-               return hwiommu_unmap_sg(dev, sglist, nents, dir);
+               return hwiommu_unmap_sg_attrs(dev, sglist, nents, dir, attrs);
 }
+EXPORT_SYMBOL(hwsw_unmap_sg_attrs);
 
 void
 hwsw_sync_single_for_cpu (struct device *dev, dma_addr_t addr, size_t size, int dir)
@@ -185,10 +192,6 @@ hwsw_dma_mapping_error (dma_addr_t dma_addr)
 }
 
 EXPORT_SYMBOL(hwsw_dma_mapping_error);
-EXPORT_SYMBOL(hwsw_map_single);
-EXPORT_SYMBOL(hwsw_unmap_single);
-EXPORT_SYMBOL(hwsw_map_sg);
-EXPORT_SYMBOL(hwsw_unmap_sg);
 EXPORT_SYMBOL(hwsw_dma_supported);
 EXPORT_SYMBOL(hwsw_alloc_coherent);
 EXPORT_SYMBOL(hwsw_free_coherent);
index 9409de5c94412c986442c881a9e31258f34b99a9..34421aed1e2ab95ff0d4f4d4e458003b409fd1a2 100644 (file)
@@ -899,16 +899,18 @@ sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
 }
 
 /**
- * sba_map_single - map one buffer and return IOVA for DMA
+ * sba_map_single_attrs - map one buffer and return IOVA for DMA
  * @dev: instance of PCI owned by the driver that's asking.
  * @addr:  driver buffer to map.
  * @size:  number of bytes to map in driver buffer.
  * @dir:  R/W or both.
+ * @attrs: optional dma attributes
  *
  * See Documentation/DMA-mapping.txt
  */
 dma_addr_t
-sba_map_single(struct device *dev, void *addr, size_t size, int dir)
+sba_map_single_attrs(struct device *dev, void *addr, size_t size, int dir,
+                    struct dma_attrs *attrs)
 {
        struct ioc *ioc;
        dma_addr_t iovp;
@@ -932,7 +934,8 @@ sba_map_single(struct device *dev, void *addr, size_t size, int dir)
                ** Device is bit capable of DMA'ing to the buffer...
                ** just return the PCI address of ptr
                */
-               DBG_BYPASS("sba_map_single() bypass mask/addr: 0x%lx/0x%lx\n",
+               DBG_BYPASS("sba_map_single_attrs() bypass mask/addr: "
+                          "0x%lx/0x%lx\n",
                           to_pci_dev(dev)->dma_mask, pci_addr);
                return pci_addr;
        }
@@ -953,7 +956,7 @@ sba_map_single(struct device *dev, void *addr, size_t size, int dir)
 
 #ifdef ASSERT_PDIR_SANITY
        spin_lock_irqsave(&ioc->res_lock, flags);
-       if (sba_check_pdir(ioc,"Check before sba_map_single()"))
+       if (sba_check_pdir(ioc,"Check before sba_map_single_attrs()"))
                panic("Sanity check failed");
        spin_unlock_irqrestore(&ioc->res_lock, flags);
 #endif
@@ -982,11 +985,12 @@ sba_map_single(struct device *dev, void *addr, size_t size, int dir)
        /* form complete address */
 #ifdef ASSERT_PDIR_SANITY
        spin_lock_irqsave(&ioc->res_lock, flags);
-       sba_check_pdir(ioc,"Check after sba_map_single()");
+       sba_check_pdir(ioc,"Check after sba_map_single_attrs()");
        spin_unlock_irqrestore(&ioc->res_lock, flags);
 #endif
        return SBA_IOVA(ioc, iovp, offset);
 }
+EXPORT_SYMBOL(sba_map_single_attrs);
 
 #ifdef ENABLE_MARK_CLEAN
 static SBA_INLINE void
@@ -1013,15 +1017,17 @@ sba_mark_clean(struct ioc *ioc, dma_addr_t iova, size_t size)
 #endif
 
 /**
- * sba_unmap_single - unmap one IOVA and free resources
+ * sba_unmap_single_attrs - unmap one IOVA and free resources
  * @dev: instance of PCI owned by the driver that's asking.
  * @iova:  IOVA of driver buffer previously mapped.
  * @size:  number of bytes mapped in driver buffer.
  * @dir:  R/W or both.
+ * @attrs: optional dma attributes
  *
  * See Documentation/DMA-mapping.txt
  */
-void sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, int dir)
+void sba_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size,
+                           int dir, struct dma_attrs *attrs)
 {
        struct ioc *ioc;
 #if DELAYED_RESOURCE_CNT > 0
@@ -1038,7 +1044,8 @@ void sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, int dir)
                /*
                ** Address does not fall w/in IOVA, must be bypassing
                */
-               DBG_BYPASS("sba_unmap_single() bypass addr: 0x%lx\n", iova);
+               DBG_BYPASS("sba_unmap_single_atttrs() bypass addr: 0x%lx\n",
+                          iova);
 
 #ifdef ENABLE_MARK_CLEAN
                if (dir == DMA_FROM_DEVICE) {
@@ -1087,7 +1094,7 @@ void sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, int dir)
        spin_unlock_irqrestore(&ioc->res_lock, flags);
 #endif /* DELAYED_RESOURCE_CNT == 0 */
 }
-
+EXPORT_SYMBOL(sba_unmap_single_attrs);
 
 /**
  * sba_alloc_coherent - allocate/map shared mem for DMA
@@ -1144,7 +1151,8 @@ sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp
         * If device can't bypass or bypass is disabled, pass the 32bit fake
         * device to map single to get an iova mapping.
         */
-       *dma_handle = sba_map_single(&ioc->sac_only_dev->dev, addr, size, 0);
+       *dma_handle = sba_map_single_attrs(&ioc->sac_only_dev->dev, addr,
+                                          size, 0, NULL);
 
        return addr;
 }
@@ -1161,7 +1169,7 @@ sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp
  */
 void sba_free_coherent (struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle)
 {
-       sba_unmap_single(dev, dma_handle, size, 0);
+       sba_unmap_single_attrs(dev, dma_handle, size, 0, NULL);
        free_pages((unsigned long) vaddr, get_order(size));
 }
 
@@ -1410,10 +1418,12 @@ sba_coalesce_chunks(struct ioc *ioc, struct device *dev,
  * @sglist:  array of buffer/length pairs
  * @nents:  number of entries in list
  * @dir:  R/W or both.
+ * @attrs: optional dma attributes
  *
  * See Documentation/DMA-mapping.txt
  */
-int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int dir)
+int sba_map_sg_attrs(struct device *dev, struct scatterlist *sglist, int nents,
+                    int dir, struct dma_attrs *attrs)
 {
        struct ioc *ioc;
        int coalesced, filled = 0;
@@ -1441,16 +1451,16 @@ int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int di
        /* Fast path single entry scatterlists. */
        if (nents == 1) {
                sglist->dma_length = sglist->length;
-               sglist->dma_address = sba_map_single(dev, sba_sg_address(sglist), sglist->length, dir);
+               sglist->dma_address = sba_map_single_attrs(dev, sba_sg_address(sglist), sglist->length, dir, attrs);
                return 1;
        }
 
 #ifdef ASSERT_PDIR_SANITY
        spin_lock_irqsave(&ioc->res_lock, flags);
-       if (sba_check_pdir(ioc,"Check before sba_map_sg()"))
+       if (sba_check_pdir(ioc,"Check before sba_map_sg_attrs()"))
        {
                sba_dump_sg(ioc, sglist, nents);
-               panic("Check before sba_map_sg()");
+               panic("Check before sba_map_sg_attrs()");
        }
        spin_unlock_irqrestore(&ioc->res_lock, flags);
 #endif
@@ -1479,10 +1489,10 @@ int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int di
 
 #ifdef ASSERT_PDIR_SANITY
        spin_lock_irqsave(&ioc->res_lock, flags);
-       if (sba_check_pdir(ioc,"Check after sba_map_sg()"))
+       if (sba_check_pdir(ioc,"Check after sba_map_sg_attrs()"))
        {
                sba_dump_sg(ioc, sglist, nents);
-               panic("Check after sba_map_sg()\n");
+               panic("Check after sba_map_sg_attrs()\n");
        }
        spin_unlock_irqrestore(&ioc->res_lock, flags);
 #endif
@@ -1492,18 +1502,20 @@ int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int di
 
        return filled;
 }
-
+EXPORT_SYMBOL(sba_map_sg_attrs);
 
 /**
- * sba_unmap_sg - unmap Scatter/Gather list
+ * sba_unmap_sg_attrs - unmap Scatter/Gather list
  * @dev: instance of PCI owned by the driver that's asking.
  * @sglist:  array of buffer/length pairs
  * @nents:  number of entries in list
  * @dir:  R/W or both.
+ * @attrs: optional dma attributes
  *
  * See Documentation/DMA-mapping.txt
  */
-void sba_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, int dir)
+void sba_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist,
+                       int nents, int dir, struct dma_attrs *attrs)
 {
 #ifdef ASSERT_PDIR_SANITY
        struct ioc *ioc;
@@ -1518,13 +1530,14 @@ void sba_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, in
        ASSERT(ioc);
 
        spin_lock_irqsave(&ioc->res_lock, flags);
-       sba_check_pdir(ioc,"Check before sba_unmap_sg()");
+       sba_check_pdir(ioc,"Check before sba_unmap_sg_attrs()");
        spin_unlock_irqrestore(&ioc->res_lock, flags);
 #endif
 
        while (nents && sglist->dma_length) {
 
-               sba_unmap_single(dev, sglist->dma_address, sglist->dma_length, dir);
+               sba_unmap_single_attrs(dev, sglist->dma_address,
+                                      sglist->dma_length, dir, attrs);
                sglist = sg_next(sglist);
                nents--;
        }
@@ -1533,11 +1546,12 @@ void sba_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, in
 
 #ifdef ASSERT_PDIR_SANITY
        spin_lock_irqsave(&ioc->res_lock, flags);
-       sba_check_pdir(ioc,"Check after sba_unmap_sg()");
+       sba_check_pdir(ioc,"Check after sba_unmap_sg_attrs()");
        spin_unlock_irqrestore(&ioc->res_lock, flags);
 #endif
 
 }
+EXPORT_SYMBOL(sba_unmap_sg_attrs);
 
 /**************************************************************
 *
@@ -1918,15 +1932,13 @@ static const struct file_operations ioc_fops = {
 static void __init
 ioc_proc_init(void)
 {
-       struct proc_dir_entry *dir, *entry;
+       struct proc_dir_entry *dir;
 
        dir = proc_mkdir("bus/mckinley", NULL);
        if (!dir)
                return;
 
-       entry = create_proc_entry(ioc_list->name, 0, dir);
-       if (entry)
-               entry->proc_fops = &ioc_fops;
+       proc_create(ioc_list->name, 0, dir, &ioc_fops);
 }
 #endif
 
@@ -2166,10 +2178,6 @@ sba_page_override(char *str)
 __setup("sbapagesize=",sba_page_override);
 
 EXPORT_SYMBOL(sba_dma_mapping_error);
-EXPORT_SYMBOL(sba_map_single);
-EXPORT_SYMBOL(sba_unmap_single);
-EXPORT_SYMBOL(sba_map_sg);
-EXPORT_SYMBOL(sba_unmap_sg);
 EXPORT_SYMBOL(sba_dma_supported);
 EXPORT_SYMBOL(sba_alloc_coherent);
 EXPORT_SYMBOL(sba_free_coherent);
index eb0c32a85fd737c3154a016a609cd99b13216266..23cafc80d2a455478197ea21350ee69faa468ae9 100644 (file)
@@ -210,21 +210,23 @@ static void do_softint(struct work_struct *private_)
        printk(KERN_ERR "simserial: do_softint called\n");
 }
 
-static void rs_put_char(struct tty_struct *tty, unsigned char ch)
+static int rs_put_char(struct tty_struct *tty, unsigned char ch)
 {
        struct async_struct *info = (struct async_struct *)tty->driver_data;
        unsigned long flags;
 
-       if (!tty || !info->xmit.buf) return;
+       if (!tty || !info->xmit.buf)
+               return 0;
 
        local_irq_save(flags);
        if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) == 0) {
                local_irq_restore(flags);
-               return;
+               return 0;
        }
        info->xmit.buf[info->xmit.head] = ch;
        info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1);
        local_irq_restore(flags);
+       return 1;
 }
 
 static void transmit_chars(struct async_struct *info, int *intr_done)
@@ -621,7 +623,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
         * the line discipline to only process XON/XOFF characters.
         */
        shutdown(info);
-       if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty);
+       if (tty->ops->flush_buffer)
+               tty->ops->flush_buffer(tty);
        if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty);
        info->event = 0;
        info->tty = NULL;
index 230a6f92367fc3a966d362e2f8126419396b1a55..c64a55af9b95b43651dd2c4e0cf281e8422c99d2 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/sched.h>
 #include <linux/pid.h>
 #include <linux/clocksource.h>
-
+#include <linux/kbuild.h>
 #include <asm-ia64/processor.h>
 #include <asm-ia64/ptrace.h>
 #include <asm-ia64/siginfo.h>
 #include "../kernel/sigframe.h"
 #include "../kernel/fsyscall_gtod_data.h"
 
-#define DEFINE(sym, val) \
-        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : : )
-
 void foo(void)
 {
        DEFINE(IA64_TASK_SIZE, sizeof (struct task_struct));
index c8e403752a0c54d5c519b6ada5f3df1b68508bac..7fbb51e10bbe04e70c2cc66570400f3569f3804c 100644 (file)
@@ -6695,16 +6695,12 @@ pfm_init(void)
        /*
         * create /proc/perfmon (mostly for debugging purposes)
         */
-       perfmon_dir = create_proc_entry("perfmon", S_IRUGO, NULL);
+       perfmon_dir = proc_create("perfmon", S_IRUGO, NULL, &pfm_proc_fops);
        if (perfmon_dir == NULL) {
                printk(KERN_ERR "perfmon: cannot create /proc entry, perfmon disabled\n");
                pmu_conf = NULL;
                return -1;
        }
-       /*
-        * install customized file operations for /proc/perfmon entry
-        */
-       perfmon_dir->proc_fops = &pfm_proc_fops;
 
        /*
         * create /proc/sys/kernel/perfmon (for debugging purposes)
index a5ea817cbcbf0ad19ec512c4d74a9348d14c0b21..58dcfac5ea882ec5529ffdec98d3219cbb58b27d 100644 (file)
@@ -183,7 +183,7 @@ do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall
 #endif
 
        /* deal with pending signal delivery */
-       if (test_thread_flag(TIF_SIGPENDING)||test_thread_flag(TIF_RESTORE_SIGMASK))
+       if (test_thread_flag(TIF_SIGPENDING))
                ia64_do_signal(scr, in_syscall);
 
        /* copy user rbs to kernel rbs */
index b11bb50a197a68ff8aa5f8661ef7552618940c56..ecb9eb78d6877685de4d677d52e4b21292de4ddc 100644 (file)
@@ -648,18 +648,16 @@ salinfo_init(void)
                if (!dir)
                        continue;
 
-               entry = create_proc_entry("event", S_IRUSR, dir);
+               entry = proc_create_data("event", S_IRUSR, dir,
+                                        &salinfo_event_fops, data);
                if (!entry)
                        continue;
-               entry->data = data;
-               entry->proc_fops = &salinfo_event_fops;
                *sdir++ = entry;
 
-               entry = create_proc_entry("data", S_IRUSR | S_IWUSR, dir);
+               entry = proc_create_data("data", S_IRUSR | S_IWUSR, dir,
+                                        &salinfo_data_fops, data);
                if (!entry)
                        continue;
-               entry->data = data;
-               entry->proc_fops = &salinfo_data_fops;
                *sdir++ = entry;
 
                /* we missed any events before now */
index 16483be18c0b8c6c33834fdb5e87ffe1da52bf70..d7ad42b77d41a2c5d4d105bcfe6dbf42c4984d7c 100644 (file)
@@ -873,7 +873,8 @@ identify_siblings(struct cpuinfo_ia64 *c)
        u16 pltid;
        pal_logical_to_physical_t info;
 
-       if ((status = ia64_pal_logical_to_phys(-1, &info)) != PAL_STATUS_SUCCESS) {
+       status = ia64_pal_logical_to_phys(-1, &info);
+       if (status != PAL_STATUS_SUCCESS) {
                if (status != PAL_STATUS_UNIMPLEMENTED) {
                        printk(KERN_ERR
                                "ia64_pal_logical_to_phys failed with %ld\n",
@@ -885,8 +886,13 @@ identify_siblings(struct cpuinfo_ia64 *c)
                info.overview_cpp  = 1;
                info.overview_tpc  = 1;
        }
-       if ((status = ia64_sal_physical_id_info(&pltid)) != PAL_STATUS_SUCCESS) {
-               printk(KERN_ERR "ia64_sal_pltid failed with %ld\n", status);
+
+       status = ia64_sal_physical_id_info(&pltid);
+       if (status != PAL_STATUS_SUCCESS) {
+               if (status != PAL_STATUS_UNIMPLEMENTED)
+                       printk(KERN_ERR
+                               "ia64_sal_pltid failed with %ld\n",
+                               status);
                return;
        }
 
index a2484fc1a06c43482e575888ca1991d45faf43e7..abb17a613b172f2feac86f38981c255d226864ac 100644 (file)
 
 static struct ia64_cpu *sysfs_cpus;
 
+void arch_fix_phys_package_id(int num, u32 slot)
+{
+#ifdef CONFIG_SMP
+       if (cpu_data(num)->socket_id == -1)
+               cpu_data(num)->socket_id = slot;
+#endif
+}
+EXPORT_SYMBOL_GPL(arch_fix_phys_package_id);
+
 int arch_register_cpu(int num)
 {
 #if defined (CONFIG_ACPI) && defined (CONFIG_HOTPLUG_CPU)
index 2a90c32024f4419fa5cc8f7d918e536c2d934d33..e77995a6e3ed35dc50d6674aba025666f0f648bb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001-2006 Silicon Graphics, Inc.  All rights reserved.
+ * Copyright (C) 2001-2008 Silicon Graphics, Inc.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
@@ -177,12 +177,13 @@ failed:
  * uncached_alloc_page
  *
  * @starting_nid: node id of node to start with, or -1
+ * @n_pages: number of contiguous pages to allocate
  *
- * Allocate 1 uncached page. Allocates on the requested node. If no
- * uncached pages are available on the requested node, roundrobin starting
- * with the next higher node.
+ * Allocate the specified number of contiguous uncached pages on the
+ * the requested node. If not enough contiguous uncached pages are available
+ * on the requested node, roundrobin starting with the next higher node.
  */
-unsigned long uncached_alloc_page(int starting_nid)
+unsigned long uncached_alloc_page(int starting_nid, int n_pages)
 {
        unsigned long uc_addr;
        struct uncached_pool *uc_pool;
@@ -202,7 +203,8 @@ unsigned long uncached_alloc_page(int starting_nid)
                if (uc_pool->pool == NULL)
                        continue;
                do {
-                       uc_addr = gen_pool_alloc(uc_pool->pool, PAGE_SIZE);
+                       uc_addr = gen_pool_alloc(uc_pool->pool,
+                                                n_pages * PAGE_SIZE);
                        if (uc_addr != 0)
                                return uc_addr;
                } while (uncached_add_chunk(uc_pool, nid) == 0);
@@ -217,11 +219,12 @@ EXPORT_SYMBOL(uncached_alloc_page);
 /*
  * uncached_free_page
  *
- * @uc_addr: uncached address of page to free
+ * @uc_addr: uncached address of first page to free
+ * @n_pages: number of contiguous pages to free
  *
- * Free a single uncached page.
+ * Free the specified number of uncached pages.
  */
-void uncached_free_page(unsigned long uc_addr)
+void uncached_free_page(unsigned long uc_addr, int n_pages)
 {
        int nid = paddr_to_nid(uc_addr - __IA64_UNCACHED_OFFSET);
        struct gen_pool *pool = uncached_pools[nid].pool;
@@ -232,7 +235,7 @@ void uncached_free_page(unsigned long uc_addr)
        if ((uc_addr & (0XFUL << 60)) != __IA64_UNCACHED_OFFSET)
                panic("uncached_free_page invalid address %lx\n", uc_addr);
 
-       gen_pool_free(pool, uc_addr, PAGE_SIZE);
+       gen_pool_free(pool, uc_addr, n_pages * PAGE_SIZE);
 }
 EXPORT_SYMBOL(uncached_free_page);
 
index d52ec4e83409126647984095dd52bced8856d314..8caf42471f0d1e72d3b2adc007a9d8e8dcc76bf0 100644 (file)
@@ -168,7 +168,10 @@ setup_ptcg_sem(int max_purges, int nptcg_from)
        static int firstcpu = 1;
 
        if (toolatetochangeptcgsem) {
-               BUG_ON(max_purges < nptcg);
+               if (nptcg_from == NPTCG_FROM_PAL && max_purges == 0)
+                       BUG_ON(1 < nptcg);
+               else
+                       BUG_ON(max_purges < nptcg);
                return;
        }
 
index dfc6bf1c7b412084a6a3038a6b2bb35fb0c1da7d..49d3120415eb740154a5469be144e51598775d04 100644 (file)
@@ -550,11 +550,12 @@ static int __init sn2_ptc_init(void)
        if (!ia64_platform_is("sn2"))
                return 0;
 
-       if (!(proc_sn2_ptc = create_proc_entry(PTC_BASENAME, 0444, NULL))) {
+       proc_sn2_ptc = proc_create(PTC_BASENAME, 0444,
+                                  NULL, &proc_sn2_ptc_operations);
+       if (!&proc_sn2_ptc_operations) {
                printk(KERN_ERR "unable to create %s proc entry", PTC_BASENAME);
                return -EINVAL;
        }
-       proc_sn2_ptc->proc_fops = &proc_sn2_ptc_operations;
        spin_lock_init(&sn2_global_ptc_lock);
        return 0;
 }
index 62b3e9a496acc7bd0d716c74931cd6e58db78bf5..2526e5c783a42514fe6111b78c8c70c0233c4838 100644 (file)
@@ -139,30 +139,21 @@ static const struct file_operations proc_sn_topo_fops = {
 void register_sn_procfs(void)
 {
        static struct proc_dir_entry *sgi_proc_dir = NULL;
-       struct proc_dir_entry *pde;
 
        BUG_ON(sgi_proc_dir != NULL);
        if (!(sgi_proc_dir = proc_mkdir("sgi_sn", NULL)))
                return;
 
-       pde = create_proc_entry("partition_id", 0444, sgi_proc_dir);
-       if (pde)
-               pde->proc_fops = &proc_partition_id_fops;
-       pde = create_proc_entry("system_serial_number", 0444, sgi_proc_dir);
-       if (pde)
-               pde->proc_fops = &proc_system_sn_fops;
-       pde = create_proc_entry("licenseID", 0444, sgi_proc_dir);
-       if (pde)
-               pde->proc_fops = &proc_license_id_fops;
-       pde = create_proc_entry("sn_force_interrupt", 0644, sgi_proc_dir);
-       if (pde)
-               pde->proc_fops = &proc_sn_force_intr_fops;
-       pde = create_proc_entry("coherence_id", 0444, sgi_proc_dir);
-       if (pde)
-               pde->proc_fops = &proc_coherence_id_fops;
-       pde = create_proc_entry("sn_topology", 0444, sgi_proc_dir);
-       if (pde)
-               pde->proc_fops = &proc_sn_topo_fops;
+       proc_create("partition_id", 0444, sgi_proc_dir,
+                   &proc_partition_id_fops);
+       proc_create("system_serial_number", 0444, sgi_proc_dir,
+                   &proc_system_sn_fops);
+       proc_create("licenseID", 0444, sgi_proc_dir, &proc_license_id_fops);
+       proc_create("sn_force_interrupt", 0644, sgi_proc_dir,
+                   &proc_sn_force_intr_fops);
+       proc_create("coherence_id", 0444, sgi_proc_dir,
+                   &proc_coherence_id_fops);
+       proc_create("sn_topology", 0444, sgi_proc_dir, &proc_sn_topo_fops);
 }
 
 #endif /* CONFIG_PROC_FS */
index 18b94b792d5491bad4ccf3f650ce0feecfaed073..52175af299a0424516fc3299c8509487581956dc 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/dma-attrs.h>
 #include <asm/dma.h>
 #include <asm/sn/intr.h>
 #include <asm/sn/pcibus_provider_defs.h>
@@ -149,11 +150,12 @@ void sn_dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
 EXPORT_SYMBOL(sn_dma_free_coherent);
 
 /**
- * sn_dma_map_single - map a single page for DMA
+ * sn_dma_map_single_attrs - map a single page for DMA
  * @dev: device to map for
  * @cpu_addr: kernel virtual address of the region to map
  * @size: size of the region
  * @direction: DMA direction
+ * @attrs: optional dma attributes
  *
  * Map the region pointed to by @cpu_addr for DMA and return the
  * DMA address.
@@ -163,42 +165,59 @@ EXPORT_SYMBOL(sn_dma_free_coherent);
  * no way of saving the dmamap handle from the alloc to later free
  * (which is pretty much unacceptable).
  *
+ * mappings with the DMA_ATTR_WRITE_BARRIER get mapped with
+ * dma_map_consistent() so that writes force a flush of pending DMA.
+ * (See "SGI Altix Architecture Considerations for Linux Device Drivers",
+ * Document Number: 007-4763-001)
+ *
  * TODO: simplify our interface;
  *       figure out how to save dmamap handle so can use two step.
  */
-dma_addr_t sn_dma_map_single(struct device *dev, void *cpu_addr, size_t size,
-                            int direction)
+dma_addr_t sn_dma_map_single_attrs(struct device *dev, void *cpu_addr,
+                                  size_t size, int direction,
+                                  struct dma_attrs *attrs)
 {
        dma_addr_t dma_addr;
        unsigned long phys_addr;
        struct pci_dev *pdev = to_pci_dev(dev);
        struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
+       int dmabarr;
+
+       dmabarr = dma_get_attr(DMA_ATTR_WRITE_BARRIER, attrs);
 
        BUG_ON(dev->bus != &pci_bus_type);
 
        phys_addr = __pa(cpu_addr);
-       dma_addr = provider->dma_map(pdev, phys_addr, size, SN_DMA_ADDR_PHYS);
+       if (dmabarr)
+               dma_addr = provider->dma_map_consistent(pdev, phys_addr,
+                                                       size, SN_DMA_ADDR_PHYS);
+       else
+               dma_addr = provider->dma_map(pdev, phys_addr, size,
+                                            SN_DMA_ADDR_PHYS);
+
        if (!dma_addr) {
                printk(KERN_ERR "%s: out of ATEs\n", __func__);
                return 0;
        }
        return dma_addr;
 }
-EXPORT_SYMBOL(sn_dma_map_single);
+EXPORT_SYMBOL(sn_dma_map_single_attrs);
 
 /**
- * sn_dma_unmap_single - unamp a DMA mapped page
+ * sn_dma_unmap_single_attrs - unamp a DMA mapped page
  * @dev: device to sync
  * @dma_addr: DMA address to sync
  * @size: size of region
  * @direction: DMA direction
+ * @attrs: optional dma attributes
  *
  * This routine is supposed to sync the DMA region specified
  * by @dma_handle into the coherence domain.  On SN, we're always cache
  * coherent, so we just need to free any ATEs associated with this mapping.
  */
-void sn_dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-                        int direction)
+void sn_dma_unmap_single_attrs(struct device *dev, dma_addr_t dma_addr,
+                              size_t size, int direction,
+                              struct dma_attrs *attrs)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
@@ -207,19 +226,21 @@ void sn_dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 
        provider->dma_unmap(pdev, dma_addr, direction);
 }
-EXPORT_SYMBOL(sn_dma_unmap_single);
+EXPORT_SYMBOL(sn_dma_unmap_single_attrs);
 
 /**
- * sn_dma_unmap_sg - unmap a DMA scatterlist
+ * sn_dma_unmap_sg_attrs - unmap a DMA scatterlist
  * @dev: device to unmap
  * @sg: scatterlist to unmap
  * @nhwentries: number of scatterlist entries
  * @direction: DMA direction
+ * @attrs: optional dma attributes
  *
  * Unmap a set of streaming mode DMA translations.
  */
-void sn_dma_unmap_sg(struct device *dev, struct scatterlist *sgl,
-                    int nhwentries, int direction)
+void sn_dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl,
+                          int nhwentries, int direction,
+                          struct dma_attrs *attrs)
 {
        int i;
        struct pci_dev *pdev = to_pci_dev(dev);
@@ -234,25 +255,34 @@ void sn_dma_unmap_sg(struct device *dev, struct scatterlist *sgl,
                sg->dma_length = 0;
        }
 }
-EXPORT_SYMBOL(sn_dma_unmap_sg);
+EXPORT_SYMBOL(sn_dma_unmap_sg_attrs);
 
 /**
- * sn_dma_map_sg - map a scatterlist for DMA
+ * sn_dma_map_sg_attrs - map a scatterlist for DMA
  * @dev: device to map for
  * @sg: scatterlist to map
  * @nhwentries: number of entries
  * @direction: direction of the DMA transaction
+ * @attrs: optional dma attributes
+ *
+ * mappings with the DMA_ATTR_WRITE_BARRIER get mapped with
+ * dma_map_consistent() so that writes force a flush of pending DMA.
+ * (See "SGI Altix Architecture Considerations for Linux Device Drivers",
+ * Document Number: 007-4763-001)
  *
  * Maps each entry of @sg for DMA.
  */
-int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nhwentries,
-                 int direction)
+int sn_dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
+                       int nhwentries, int direction, struct dma_attrs *attrs)
 {
        unsigned long phys_addr;
        struct scatterlist *saved_sg = sgl, *sg;
        struct pci_dev *pdev = to_pci_dev(dev);
        struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
        int i;
+       int dmabarr;
+
+       dmabarr = dma_get_attr(DMA_ATTR_WRITE_BARRIER, attrs);
 
        BUG_ON(dev->bus != &pci_bus_type);
 
@@ -260,11 +290,19 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nhwentries,
         * Setup a DMA address for each entry in the scatterlist.
         */
        for_each_sg(sgl, sg, nhwentries, i) {
+               dma_addr_t dma_addr;
                phys_addr = SG_ENT_PHYS_ADDRESS(sg);
-               sg->dma_address = provider->dma_map(pdev,
-                                                   phys_addr, sg->length,
-                                                   SN_DMA_ADDR_PHYS);
+               if (dmabarr)
+                       dma_addr = provider->dma_map_consistent(pdev,
+                                                               phys_addr,
+                                                               sg->length,
+                                                               SN_DMA_ADDR_PHYS);
+               else
+                       dma_addr = provider->dma_map(pdev, phys_addr,
+                                                    sg->length,
+                                                    SN_DMA_ADDR_PHYS);
 
+               sg->dma_address = dma_addr;
                if (!sg->dma_address) {
                        printk(KERN_ERR "%s: out of ATEs\n", __func__);
 
@@ -272,7 +310,8 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nhwentries,
                         * Free any successfully allocated entries.
                         */
                        if (i > 0)
-                               sn_dma_unmap_sg(dev, saved_sg, i, direction);
+                               sn_dma_unmap_sg_attrs(dev, saved_sg, i,
+                                                     direction, attrs);
                        return 0;
                }
 
@@ -281,7 +320,7 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nhwentries,
 
        return nhwentries;
 }
-EXPORT_SYMBOL(sn_dma_map_sg);
+EXPORT_SYMBOL(sn_dma_map_sg_attrs);
 
 void sn_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
                                size_t size, int direction)
index 246a8820c2236b814e636985078b93cf78dd6c3b..b1f012f6c4931636551dcb832c4044754691565e 100644 (file)
 #include <linux/stddef.h>
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
+#include <linux/kbuild.h>
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
 #include <asm/amigahw.h>
 #include <linux/font.h>
 
-#define DEFINE(sym, val) \
-       asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
 int main(void)
 {
        /* offsets into the task struct */
index 5b2799eb96a68f930d6d93e30873f6c796487c25..326fb9978094961221c14ce4a53a596ee3934816 100644 (file)
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/init.h>
-#include <linux/proc_fs.h>
 #include <linux/interrupt.h>
 
 #include <asm/bootinfo.h>
 
 int iop_scc_present,iop_ism_present;
 
-#ifdef CONFIG_PROC_FS
-static int iop_get_proc_info(char *, char **, off_t, int);
-#endif /* CONFIG_PROC_FS */
-
 /* structure for tracking channel listeners */
 
 struct listener {
@@ -299,12 +294,6 @@ void __init iop_init(void)
                iop_listeners[IOP_NUM_ISM][i].devname = NULL;
                iop_listeners[IOP_NUM_ISM][i].handler = NULL;
        }
-
-#if 0  /* Crashing in 2.4 now, not yet sure why.   --jmt */
-#ifdef CONFIG_PROC_FS
-       create_proc_info_entry("mac_iop", 0, &proc_root, iop_get_proc_info);
-#endif
-#endif
 }
 
 /*
@@ -637,77 +626,3 @@ irqreturn_t iop_ism_irq(int irq, void *dev_id)
        }
        return IRQ_HANDLED;
 }
-
-#ifdef CONFIG_PROC_FS
-
-char *iop_chan_state(int state)
-{
-       switch(state) {
-               case IOP_MSG_IDLE       : return "idle      ";
-               case IOP_MSG_NEW        : return "new       ";
-               case IOP_MSG_RCVD       : return "received  ";
-               case IOP_MSG_COMPLETE   : return "completed ";
-               default                 : return "unknown   ";
-       }
-}
-
-int iop_dump_one_iop(char *buf, int iop_num, char *iop_name)
-{
-       int i,len = 0;
-       volatile struct mac_iop *iop = iop_base[iop_num];
-
-       len += sprintf(buf+len, "%s IOP channel states:\n\n", iop_name);
-       len += sprintf(buf+len, "##  send_state  recv_state  device\n");
-       len += sprintf(buf+len, "------------------------------------------------\n");
-       for (i = 0 ; i < NUM_IOP_CHAN ; i++) {
-               len += sprintf(buf+len, "%2d  %10s  %10s  %s\n", i,
-                       iop_chan_state(iop_readb(iop, IOP_ADDR_SEND_STATE+i)),
-                       iop_chan_state(iop_readb(iop, IOP_ADDR_RECV_STATE+i)),
-                       iop_listeners[iop_num][i].handler?
-                                     iop_listeners[iop_num][i].devname : "");
-
-       }
-       len += sprintf(buf+len, "\n");
-       return len;
-}
-
-static int iop_get_proc_info(char *buf, char **start, off_t pos, int count)
-{
-       int len, cnt;
-
-       cnt = 0;
-       len =  sprintf(buf, "IOPs detected:\n\n");
-
-       if (iop_scc_present) {
-               len += sprintf(buf+len, "SCC IOP (%p): status %02X\n",
-                               iop_base[IOP_NUM_SCC],
-                               (uint) iop_base[IOP_NUM_SCC]->status_ctrl);
-       }
-       if (iop_ism_present) {
-               len += sprintf(buf+len, "ISM IOP (%p): status %02X\n\n",
-                               iop_base[IOP_NUM_ISM],
-                               (uint) iop_base[IOP_NUM_ISM]->status_ctrl);
-       }
-
-       if (iop_scc_present) {
-               len += iop_dump_one_iop(buf+len, IOP_NUM_SCC, "SCC");
-
-       }
-
-       if (iop_ism_present) {
-               len += iop_dump_one_iop(buf+len, IOP_NUM_ISM, "ISM");
-
-       }
-
-       if (len >= pos) {
-               if (!*start) {
-                       *start = buf + pos;
-                       cnt = len - pos;
-               } else {
-                       cnt += len;
-               }
-       }
-       return (count > cnt) ? cnt : count;
-}
-
-#endif /* CONFIG_PROC_FS */
index a2bb01f5964230dccb312006a2832f5f4fac8f53..d8fb9c5303ccf931bca250fa61e410849e886492 100644 (file)
@@ -69,6 +69,7 @@ void __init m68k_setup_node(int node)
  */
 
 void *empty_zero_page;
+EXPORT_SYMBOL(empty_zero_page);
 
 void show_mem(void)
 {
index d97b89bae53cf10c824422308254148e55c6e325..fd0c685a7f11c13de748a5dc2551b4ee73651aa5 100644 (file)
 #include <linux/kernel_stat.h>
 #include <linux/ptrace.h>
 #include <linux/hardirq.h>
+#include <linux/kbuild.h>
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
 #include <asm/thread_info.h>
 
-#define DEFINE(sym, val) \
-        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : : )
-
 int main(void)
 {
        /* offsets into the task struct */
index 9ee67a95f6b96b57f17e34891c0c61366d48b18a..08923e6825b5421adac39ad3e880f8203c11e6d3 100644 (file)
@@ -18,8 +18,9 @@
  *  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/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/stat.h>
 #include <asm/page.h>
 #include <asm/io.h>
 
 #include <excite.h>
 
-static int excite_get_unit_id(char *buf, char **addr, off_t offs, int size)
+static int excite_unit_id_proc_show(struct seq_file *m, void *v)
 {
-       const int len = snprintf(buf, PAGE_SIZE, "%06x", unit_id);
-       const int w = len - offs;
-       *addr = buf + offs;
-       return w < size ? w : size;
+       seq_printf(m, "%06x", unit_id);
+       return 0;
 }
 
+static int excite_unit_id_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, excite_unit_id_proc_show, NULL);
+}
+
+static const struct file_operations excite_unit_id_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = excite_unit_id_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
 static int
 excite_bootrom_read(char *page, char **start, off_t off, int count,
                  int *eof, void *data)
@@ -65,12 +77,12 @@ excite_bootrom_read(char *page, char **start, off_t off, int count,
 void excite_procfs_init(void)
 {
        /* Create & populate /proc/excite */
-       struct proc_dir_entry * const pdir = proc_mkdir("excite", &proc_root);
+       struct proc_dir_entry * const pdir = proc_mkdir("excite", NULL);
        if (pdir) {
                struct proc_dir_entry * e;
 
-               e = create_proc_info_entry("unit_id", S_IRUGO, pdir,
-                                          excite_get_unit_id);
+               e = proc_create("unit_id", S_IRUGO, pdir,
+                               &excite_unit_id_proc_fops);
                if (e) e->size = 6;
 
                e = create_proc_read_entry("bootrom", S_IRUGO, pdir,
index 5bf03b3c4150c31474831a163f7dabc502798a45..72942226fcdd5b285cc8eed3fc301dc9c96b507d 100644 (file)
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
-
+#include <linux/kbuild.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
 
-#define text(t) __asm__("\n->#" t)
-#define _offset(type, member) (&(((type *)NULL)->member))
-#define offset(string, ptr, member) \
-       __asm__("\n->" string " %0" : : "i" (_offset(ptr, member)))
-#define constant(string, member) \
-       __asm__("\n->" string " %0" : : "ri" (member))
-#define size(string, size) \
-       __asm__("\n->" string " %0" : : "i" (sizeof(size)))
-#define linefeed text("")
-
 void output_ptreg_defines(void)
 {
-       text("MIPS pt_regs offsets.");
-       offset("PT_R0", struct pt_regs, regs[0]);
-       offset("PT_R1", struct pt_regs, regs[1]);
-       offset("PT_R2", struct pt_regs, regs[2]);
-       offset("PT_R3", struct pt_regs, regs[3]);
-       offset("PT_R4", struct pt_regs, regs[4]);
-       offset("PT_R5", struct pt_regs, regs[5]);
-       offset("PT_R6", struct pt_regs, regs[6]);
-       offset("PT_R7", struct pt_regs, regs[7]);
-       offset("PT_R8", struct pt_regs, regs[8]);
-       offset("PT_R9", struct pt_regs, regs[9]);
-       offset("PT_R10", struct pt_regs, regs[10]);
-       offset("PT_R11", struct pt_regs, regs[11]);
-       offset("PT_R12", struct pt_regs, regs[12]);
-       offset("PT_R13", struct pt_regs, regs[13]);
-       offset("PT_R14", struct pt_regs, regs[14]);
-       offset("PT_R15", struct pt_regs, regs[15]);
-       offset("PT_R16", struct pt_regs, regs[16]);
-       offset("PT_R17", struct pt_regs, regs[17]);
-       offset("PT_R18", struct pt_regs, regs[18]);
-       offset("PT_R19", struct pt_regs, regs[19]);
-       offset("PT_R20", struct pt_regs, regs[20]);
-       offset("PT_R21", struct pt_regs, regs[21]);
-       offset("PT_R22", struct pt_regs, regs[22]);
-       offset("PT_R23", struct pt_regs, regs[23]);
-       offset("PT_R24", struct pt_regs, regs[24]);
-       offset("PT_R25", struct pt_regs, regs[25]);
-       offset("PT_R26", struct pt_regs, regs[26]);
-       offset("PT_R27", struct pt_regs, regs[27]);
-       offset("PT_R28", struct pt_regs, regs[28]);
-       offset("PT_R29", struct pt_regs, regs[29]);
-       offset("PT_R30", struct pt_regs, regs[30]);
-       offset("PT_R31", struct pt_regs, regs[31]);
-       offset("PT_LO", struct pt_regs, lo);
-       offset("PT_HI", struct pt_regs, hi);
+       COMMENT("MIPS pt_regs offsets.");
+       OFFSET(PT_R0, pt_regs, regs[0]);
+       OFFSET(PT_R1, pt_regs, regs[1]);
+       OFFSET(PT_R2, pt_regs, regs[2]);
+       OFFSET(PT_R3, pt_regs, regs[3]);
+       OFFSET(PT_R4, pt_regs, regs[4]);
+       OFFSET(PT_R5, pt_regs, regs[5]);
+       OFFSET(PT_R6, pt_regs, regs[6]);
+       OFFSET(PT_R7, pt_regs, regs[7]);
+       OFFSET(PT_R8, pt_regs, regs[8]);
+       OFFSET(PT_R9, pt_regs, regs[9]);
+       OFFSET(PT_R10, pt_regs, regs[10]);
+       OFFSET(PT_R11, pt_regs, regs[11]);
+       OFFSET(PT_R12, pt_regs, regs[12]);
+       OFFSET(PT_R13, pt_regs, regs[13]);
+       OFFSET(PT_R14, pt_regs, regs[14]);
+       OFFSET(PT_R15, pt_regs, regs[15]);
+       OFFSET(PT_R16, pt_regs, regs[16]);
+       OFFSET(PT_R17, pt_regs, regs[17]);
+       OFFSET(PT_R18, pt_regs, regs[18]);
+       OFFSET(PT_R19, pt_regs, regs[19]);
+       OFFSET(PT_R20, pt_regs, regs[20]);
+       OFFSET(PT_R21, pt_regs, regs[21]);
+       OFFSET(PT_R22, pt_regs, regs[22]);
+       OFFSET(PT_R23, pt_regs, regs[23]);
+       OFFSET(PT_R24, pt_regs, regs[24]);
+       OFFSET(PT_R25, pt_regs, regs[25]);
+       OFFSET(PT_R26, pt_regs, regs[26]);
+       OFFSET(PT_R27, pt_regs, regs[27]);
+       OFFSET(PT_R28, pt_regs, regs[28]);
+       OFFSET(PT_R29, pt_regs, regs[29]);
+       OFFSET(PT_R30, pt_regs, regs[30]);
+       OFFSET(PT_R31, pt_regs, regs[31]);
+       OFFSET(PT_LO, pt_regs, lo);
+       OFFSET(PT_HI, pt_regs, hi);
 #ifdef CONFIG_CPU_HAS_SMARTMIPS
-       offset("PT_ACX", struct pt_regs, acx);
+       OFFSET(PT_ACX, pt_regs, acx);
 #endif
-       offset("PT_EPC", struct pt_regs, cp0_epc);
-       offset("PT_BVADDR", struct pt_regs, cp0_badvaddr);
-       offset("PT_STATUS", struct pt_regs, cp0_status);
-       offset("PT_CAUSE", struct pt_regs, cp0_cause);
+       OFFSET(PT_EPC, pt_regs, cp0_epc);
+       OFFSET(PT_BVADDR, pt_regs, cp0_badvaddr);
+       OFFSET(PT_STATUS, pt_regs, cp0_status);
+       OFFSET(PT_CAUSE, pt_regs, cp0_cause);
 #ifdef CONFIG_MIPS_MT_SMTC
-       offset("PT_TCSTATUS", struct pt_regs, cp0_tcstatus);
+       OFFSET(PT_TCSTATUS, pt_regs, cp0_tcstatus);
 #endif /* CONFIG_MIPS_MT_SMTC */
-       size("PT_SIZE", struct pt_regs);
-       linefeed;
+       DEFINE(PT_SIZE, sizeof(struct pt_regs));
+       BLANK();
 }
 
 void output_task_defines(void)
 {
-       text("MIPS task_struct offsets.");
-       offset("TASK_STATE", struct task_struct, state);
-       offset("TASK_THREAD_INFO", struct task_struct, stack);
-       offset("TASK_FLAGS", struct task_struct, flags);
-       offset("TASK_MM", struct task_struct, mm);
-       offset("TASK_PID", struct task_struct, pid);
-       size(  "TASK_STRUCT_SIZE", struct task_struct);
-       linefeed;
+       COMMENT("MIPS task_struct offsets.");
+       OFFSET(TASK_STATE, task_struct, state);
+       OFFSET(TASK_THREAD_INFO, task_struct, stack);
+       OFFSET(TASK_FLAGS, task_struct, flags);
+       OFFSET(TASK_MM, task_struct, mm);
+       OFFSET(TASK_PID, task_struct, pid);
+       DEFINE(TASK_STRUCT_SIZE, sizeof(struct task_struct));
+       BLANK();
 }
 
 void output_thread_info_defines(void)
 {
-       text("MIPS thread_info offsets.");
-       offset("TI_TASK", struct thread_info, task);
-       offset("TI_EXEC_DOMAIN", struct thread_info, exec_domain);
-       offset("TI_FLAGS", struct thread_info, flags);
-       offset("TI_TP_VALUE", struct thread_info, tp_value);
-       offset("TI_CPU", struct thread_info, cpu);
-       offset("TI_PRE_COUNT", struct thread_info, preempt_count);
-       offset("TI_ADDR_LIMIT", struct thread_info, addr_limit);
-       offset("TI_RESTART_BLOCK", struct thread_info, restart_block);
-       offset("TI_REGS", struct thread_info, regs);
-       constant("_THREAD_SIZE", THREAD_SIZE);
-       constant("_THREAD_MASK", THREAD_MASK);
-       linefeed;
+       COMMENT("MIPS thread_info offsets.");
+       OFFSET(TI_TASK, thread_info, task);
+       OFFSET(TI_EXEC_DOMAIN, thread_info, exec_domain);
+       OFFSET(TI_FLAGS, thread_info, flags);
+       OFFSET(TI_TP_VALUE, thread_info, tp_value);
+       OFFSET(TI_CPU, thread_info, cpu);
+       OFFSET(TI_PRE_COUNT, thread_info, preempt_count);
+       OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit);
+       OFFSET(TI_RESTART_BLOCK, thread_info, restart_block);
+       OFFSET(TI_REGS, thread_info, regs);
+       DEFINE(_THREAD_SIZE, THREAD_SIZE);
+       DEFINE(_THREAD_MASK, THREAD_MASK);
+       BLANK();
 }
 
 void output_thread_defines(void)
 {
-       text("MIPS specific thread_struct offsets.");
-       offset("THREAD_REG16", struct task_struct, thread.reg16);
-       offset("THREAD_REG17", struct task_struct, thread.reg17);
-       offset("THREAD_REG18", struct task_struct, thread.reg18);
-       offset("THREAD_REG19", struct task_struct, thread.reg19);
-       offset("THREAD_REG20", struct task_struct, thread.reg20);
-       offset("THREAD_REG21", struct task_struct, thread.reg21);
-       offset("THREAD_REG22", struct task_struct, thread.reg22);
-       offset("THREAD_REG23", struct task_struct, thread.reg23);
-       offset("THREAD_REG29", struct task_struct, thread.reg29);
-       offset("THREAD_REG30", struct task_struct, thread.reg30);
-       offset("THREAD_REG31", struct task_struct, thread.reg31);
-       offset("THREAD_STATUS", struct task_struct,
+       COMMENT("MIPS specific thread_struct offsets.");
+       OFFSET(THREAD_REG16, task_struct, thread.reg16);
+       OFFSET(THREAD_REG17, task_struct, thread.reg17);
+       OFFSET(THREAD_REG18, task_struct, thread.reg18);
+       OFFSET(THREAD_REG19, task_struct, thread.reg19);
+       OFFSET(THREAD_REG20, task_struct, thread.reg20);
+       OFFSET(THREAD_REG21, task_struct, thread.reg21);
+       OFFSET(THREAD_REG22, task_struct, thread.reg22);
+       OFFSET(THREAD_REG23, task_struct, thread.reg23);
+       OFFSET(THREAD_REG29, task_struct, thread.reg29);
+       OFFSET(THREAD_REG30, task_struct, thread.reg30);
+       OFFSET(THREAD_REG31, task_struct, thread.reg31);
+       OFFSET(THREAD_STATUS, task_struct,
               thread.cp0_status);
-       offset("THREAD_FPU", struct task_struct, thread.fpu);
+       OFFSET(THREAD_FPU, task_struct, thread.fpu);
 
-       offset("THREAD_BVADDR", struct task_struct, \
+       OFFSET(THREAD_BVADDR, task_struct, \
               thread.cp0_badvaddr);
-       offset("THREAD_BUADDR", struct task_struct, \
+       OFFSET(THREAD_BUADDR, task_struct, \
               thread.cp0_baduaddr);
-       offset("THREAD_ECODE", struct task_struct, \
+       OFFSET(THREAD_ECODE, task_struct, \
               thread.error_code);
-       offset("THREAD_TRAPNO", struct task_struct, thread.trap_no);
-       offset("THREAD_TRAMP", struct task_struct, \
+       OFFSET(THREAD_TRAPNO, task_struct, thread.trap_no);
+       OFFSET(THREAD_TRAMP, task_struct, \
               thread.irix_trampoline);
-       offset("THREAD_OLDCTX", struct task_struct, \
+       OFFSET(THREAD_OLDCTX, task_struct, \
               thread.irix_oldctx);
-       linefeed;
+       BLANK();
 }
 
 void output_thread_fpu_defines(void)
 {
-       offset("THREAD_FPR0",
-              struct task_struct, thread.fpu.fpr[0]);
-       offset("THREAD_FPR1",
-              struct task_struct, thread.fpu.fpr[1]);
-       offset("THREAD_FPR2",
-              struct task_struct, thread.fpu.fpr[2]);
-       offset("THREAD_FPR3",
-              struct task_struct, thread.fpu.fpr[3]);
-       offset("THREAD_FPR4",
-              struct task_struct, thread.fpu.fpr[4]);
-       offset("THREAD_FPR5",
-              struct task_struct, thread.fpu.fpr[5]);
-       offset("THREAD_FPR6",
-              struct task_struct, thread.fpu.fpr[6]);
-       offset("THREAD_FPR7",
-              struct task_struct, thread.fpu.fpr[7]);
-       offset("THREAD_FPR8",
-              struct task_struct, thread.fpu.fpr[8]);
-       offset("THREAD_FPR9",
-              struct task_struct, thread.fpu.fpr[9]);
-       offset("THREAD_FPR10",
-              struct task_struct, thread.fpu.fpr[10]);
-       offset("THREAD_FPR11",
-              struct task_struct, thread.fpu.fpr[11]);
-       offset("THREAD_FPR12",
-              struct task_struct, thread.fpu.fpr[12]);
-       offset("THREAD_FPR13",
-              struct task_struct, thread.fpu.fpr[13]);
-       offset("THREAD_FPR14",
-              struct task_struct, thread.fpu.fpr[14]);
-       offset("THREAD_FPR15",
-              struct task_struct, thread.fpu.fpr[15]);
-       offset("THREAD_FPR16",
-              struct task_struct, thread.fpu.fpr[16]);
-       offset("THREAD_FPR17",
-              struct task_struct, thread.fpu.fpr[17]);
-       offset("THREAD_FPR18",
-              struct task_struct, thread.fpu.fpr[18]);
-       offset("THREAD_FPR19",
-              struct task_struct, thread.fpu.fpr[19]);
-       offset("THREAD_FPR20",
-              struct task_struct, thread.fpu.fpr[20]);
-       offset("THREAD_FPR21",
-              struct task_struct, thread.fpu.fpr[21]);
-       offset("THREAD_FPR22",
-              struct task_struct, thread.fpu.fpr[22]);
-       offset("THREAD_FPR23",
-              struct task_struct, thread.fpu.fpr[23]);
-       offset("THREAD_FPR24",
-              struct task_struct, thread.fpu.fpr[24]);
-       offset("THREAD_FPR25",
-              struct task_struct, thread.fpu.fpr[25]);
-       offset("THREAD_FPR26",
-              struct task_struct, thread.fpu.fpr[26]);
-       offset("THREAD_FPR27",
-              struct task_struct, thread.fpu.fpr[27]);
-       offset("THREAD_FPR28",
-              struct task_struct, thread.fpu.fpr[28]);
-       offset("THREAD_FPR29",
-              struct task_struct, thread.fpu.fpr[29]);
-       offset("THREAD_FPR30",
-              struct task_struct, thread.fpu.fpr[30]);
-       offset("THREAD_FPR31",
-              struct task_struct, thread.fpu.fpr[31]);
+       OFFSET(THREAD_FPR0, task_struct, thread.fpu.fpr[0]);
+       OFFSET(THREAD_FPR1, task_struct, thread.fpu.fpr[1]);
+       OFFSET(THREAD_FPR2, task_struct, thread.fpu.fpr[2]);
+       OFFSET(THREAD_FPR3, task_struct, thread.fpu.fpr[3]);
+       OFFSET(THREAD_FPR4, task_struct, thread.fpu.fpr[4]);
+       OFFSET(THREAD_FPR5, task_struct, thread.fpu.fpr[5]);
+       OFFSET(THREAD_FPR6, task_struct, thread.fpu.fpr[6]);
+       OFFSET(THREAD_FPR7, task_struct, thread.fpu.fpr[7]);
+       OFFSET(THREAD_FPR8, task_struct, thread.fpu.fpr[8]);
+       OFFSET(THREAD_FPR9, task_struct, thread.fpu.fpr[9]);
+       OFFSET(THREAD_FPR10, task_struct, thread.fpu.fpr[10]);
+       OFFSET(THREAD_FPR11, task_struct, thread.fpu.fpr[11]);
+       OFFSET(THREAD_FPR12, task_struct, thread.fpu.fpr[12]);
+       OFFSET(THREAD_FPR13, task_struct, thread.fpu.fpr[13]);
+       OFFSET(THREAD_FPR14, task_struct, thread.fpu.fpr[14]);
+       OFFSET(THREAD_FPR15, task_struct, thread.fpu.fpr[15]);
+       OFFSET(THREAD_FPR16, task_struct, thread.fpu.fpr[16]);
+       OFFSET(THREAD_FPR17, task_struct, thread.fpu.fpr[17]);
+       OFFSET(THREAD_FPR18, task_struct, thread.fpu.fpr[18]);
+       OFFSET(THREAD_FPR19, task_struct, thread.fpu.fpr[19]);
+       OFFSET(THREAD_FPR20, task_struct, thread.fpu.fpr[20]);
+       OFFSET(THREAD_FPR21, task_struct, thread.fpu.fpr[21]);
+       OFFSET(THREAD_FPR22, task_struct, thread.fpu.fpr[22]);
+       OFFSET(THREAD_FPR23, task_struct, thread.fpu.fpr[23]);
+       OFFSET(THREAD_FPR24, task_struct, thread.fpu.fpr[24]);
+       OFFSET(THREAD_FPR25, task_struct, thread.fpu.fpr[25]);
+       OFFSET(THREAD_FPR26, task_struct, thread.fpu.fpr[26]);
+       OFFSET(THREAD_FPR27, task_struct, thread.fpu.fpr[27]);
+       OFFSET(THREAD_FPR28, task_struct, thread.fpu.fpr[28]);
+       OFFSET(THREAD_FPR29, task_struct, thread.fpu.fpr[29]);
+       OFFSET(THREAD_FPR30, task_struct, thread.fpu.fpr[30]);
+       OFFSET(THREAD_FPR31, task_struct, thread.fpu.fpr[31]);
 
-       offset("THREAD_FCR31",
-              struct task_struct, thread.fpu.fcr31);
-       linefeed;
+       OFFSET(THREAD_FCR31, task_struct, thread.fpu.fcr31);
+       BLANK();
 }
 
 void output_mm_defines(void)
 {
-       text("Size of struct page");
-       size("STRUCT_PAGE_SIZE", struct page);
-       linefeed;
-       text("Linux mm_struct offsets.");
-       offset("MM_USERS", struct mm_struct, mm_users);
-       offset("MM_PGD", struct mm_struct, pgd);
-       offset("MM_CONTEXT", struct mm_struct, context);
-       linefeed;
-       constant("_PAGE_SIZE", PAGE_SIZE);
-       constant("_PAGE_SHIFT", PAGE_SHIFT);
-       linefeed;
-       constant("_PGD_T_SIZE", sizeof(pgd_t));
-       constant("_PMD_T_SIZE", sizeof(pmd_t));
-       constant("_PTE_T_SIZE", sizeof(pte_t));
-       linefeed;
-       constant("_PGD_T_LOG2", PGD_T_LOG2);
-       constant("_PMD_T_LOG2", PMD_T_LOG2);
-       constant("_PTE_T_LOG2", PTE_T_LOG2);
-       linefeed;
-       constant("_PGD_ORDER", PGD_ORDER);
-       constant("_PMD_ORDER", PMD_ORDER);
-       constant("_PTE_ORDER", PTE_ORDER);
-       linefeed;
-       constant("_PMD_SHIFT", PMD_SHIFT);
-       constant("_PGDIR_SHIFT", PGDIR_SHIFT);
-       linefeed;
-       constant("_PTRS_PER_PGD", PTRS_PER_PGD);
-       constant("_PTRS_PER_PMD", PTRS_PER_PMD);
-       constant("_PTRS_PER_PTE", PTRS_PER_PTE);
-       linefeed;
+       COMMENT("Size of struct page");
+       DEFINE(STRUCT_PAGE_SIZE, sizeof(struct page));
+       BLANK();
+       COMMENT("Linux mm_struct offsets.");
+       OFFSET(MM_USERS, mm_struct, mm_users);
+       OFFSET(MM_PGD, mm_struct, pgd);
+       OFFSET(MM_CONTEXT, mm_struct, context);
+       BLANK();
+       DEFINE(_PAGE_SIZE, PAGE_SIZE);
+       DEFINE(_PAGE_SHIFT, PAGE_SHIFT);
+       BLANK();
+       DEFINE(_PGD_T_SIZE, sizeof(pgd_t));
+       DEFINE(_PMD_T_SIZE, sizeof(pmd_t));
+       DEFINE(_PTE_T_SIZE, sizeof(pte_t));
+       BLANK();
+       DEFINE(_PGD_T_LOG2, PGD_T_LOG2);
+       DEFINE(_PMD_T_LOG2, PMD_T_LOG2);
+       DEFINE(_PTE_T_LOG2, PTE_T_LOG2);
+       BLANK();
+       DEFINE(_PGD_ORDER, PGD_ORDER);
+       DEFINE(_PMD_ORDER, PMD_ORDER);
+       DEFINE(_PTE_ORDER, PTE_ORDER);
+       BLANK();
+       DEFINE(_PMD_SHIFT, PMD_SHIFT);
+       DEFINE(_PGDIR_SHIFT, PGDIR_SHIFT);
+       BLANK();
+       DEFINE(_PTRS_PER_PGD, PTRS_PER_PGD);
+       DEFINE(_PTRS_PER_PMD, PTRS_PER_PMD);
+       DEFINE(_PTRS_PER_PTE, PTRS_PER_PTE);
+       BLANK();
 }
 
 #ifdef CONFIG_32BIT
 void output_sc_defines(void)
 {
-       text("Linux sigcontext offsets.");
-       offset("SC_REGS", struct sigcontext, sc_regs);
-       offset("SC_FPREGS", struct sigcontext, sc_fpregs);
-       offset("SC_ACX", struct sigcontext, sc_acx);
-       offset("SC_MDHI", struct sigcontext, sc_mdhi);
-       offset("SC_MDLO", struct sigcontext, sc_mdlo);
-       offset("SC_PC", struct sigcontext, sc_pc);
-       offset("SC_FPC_CSR", struct sigcontext, sc_fpc_csr);
-       offset("SC_FPC_EIR", struct sigcontext, sc_fpc_eir);
-       offset("SC_HI1", struct sigcontext, sc_hi1);
-       offset("SC_LO1", struct sigcontext, sc_lo1);
-       offset("SC_HI2", struct sigcontext, sc_hi2);
-       offset("SC_LO2", struct sigcontext, sc_lo2);
-       offset("SC_HI3", struct sigcontext, sc_hi3);
-       offset("SC_LO3", struct sigcontext, sc_lo3);
-       linefeed;
+       COMMENT("Linux sigcontext offsets.");
+       OFFSET(SC_REGS, sigcontext, sc_regs);
+       OFFSET(SC_FPREGS, sigcontext, sc_fpregs);
+       OFFSET(SC_ACX, sigcontext, sc_acx);
+       OFFSET(SC_MDHI, sigcontext, sc_mdhi);
+       OFFSET(SC_MDLO, sigcontext, sc_mdlo);
+       OFFSET(SC_PC, sigcontext, sc_pc);
+       OFFSET(SC_FPC_CSR, sigcontext, sc_fpc_csr);
+       OFFSET(SC_FPC_EIR, sigcontext, sc_fpc_eir);
+       OFFSET(SC_HI1, sigcontext, sc_hi1);
+       OFFSET(SC_LO1, sigcontext, sc_lo1);
+       OFFSET(SC_HI2, sigcontext, sc_hi2);
+       OFFSET(SC_LO2, sigcontext, sc_lo2);
+       OFFSET(SC_HI3, sigcontext, sc_hi3);
+       OFFSET(SC_LO3, sigcontext, sc_lo3);
+       BLANK();
 }
 #endif
 
 #ifdef CONFIG_64BIT
 void output_sc_defines(void)
 {
-       text("Linux sigcontext offsets.");
-       offset("SC_REGS", struct sigcontext, sc_regs);
-       offset("SC_FPREGS", struct sigcontext, sc_fpregs);
-       offset("SC_MDHI", struct sigcontext, sc_mdhi);
-       offset("SC_MDLO", struct sigcontext, sc_mdlo);
-       offset("SC_PC", struct sigcontext, sc_pc);
-       offset("SC_FPC_CSR", struct sigcontext, sc_fpc_csr);
-       linefeed;
+       COMMENT("Linux sigcontext offsets.");
+       OFFSET(SC_REGS, sigcontext, sc_regs);
+       OFFSET(SC_FPREGS, sigcontext, sc_fpregs);
+       OFFSET(SC_MDHI, sigcontext, sc_mdhi);
+       OFFSET(SC_MDLO, sigcontext, sc_mdlo);
+       OFFSET(SC_PC, sigcontext, sc_pc);
+       OFFSET(SC_FPC_CSR, sigcontext, sc_fpc_csr);
+       BLANK();
 }
 #endif
 
 #ifdef CONFIG_MIPS32_COMPAT
 void output_sc32_defines(void)
 {
-       text("Linux 32-bit sigcontext offsets.");
-       offset("SC32_FPREGS", struct sigcontext32, sc_fpregs);
-       offset("SC32_FPC_CSR", struct sigcontext32, sc_fpc_csr);
-       offset("SC32_FPC_EIR", struct sigcontext32, sc_fpc_eir);
-       linefeed;
+       COMMENT("Linux 32-bit sigcontext offsets.");
+       OFFSET(SC32_FPREGS, sigcontext32, sc_fpregs);
+       OFFSET(SC32_FPC_CSR, sigcontext32, sc_fpc_csr);
+       OFFSET(SC32_FPC_EIR, sigcontext32, sc_fpc_eir);
+       BLANK();
 }
 #endif
 
 void output_signal_defined(void)
 {
-       text("Linux signal numbers.");
-       constant("_SIGHUP", SIGHUP);
-       constant("_SIGINT", SIGINT);
-       constant("_SIGQUIT", SIGQUIT);
-       constant("_SIGILL", SIGILL);
-       constant("_SIGTRAP", SIGTRAP);
-       constant("_SIGIOT", SIGIOT);
-       constant("_SIGABRT", SIGABRT);
-       constant("_SIGEMT", SIGEMT);
-       constant("_SIGFPE", SIGFPE);
-       constant("_SIGKILL", SIGKILL);
-       constant("_SIGBUS", SIGBUS);
-       constant("_SIGSEGV", SIGSEGV);
-       constant("_SIGSYS", SIGSYS);
-       constant("_SIGPIPE", SIGPIPE);
-       constant("_SIGALRM", SIGALRM);
-       constant("_SIGTERM", SIGTERM);
-       constant("_SIGUSR1", SIGUSR1);
-       constant("_SIGUSR2", SIGUSR2);
-       constant("_SIGCHLD", SIGCHLD);
-       constant("_SIGPWR", SIGPWR);
-       constant("_SIGWINCH", SIGWINCH);
-       constant("_SIGURG", SIGURG);
-       constant("_SIGIO", SIGIO);
-       constant("_SIGSTOP", SIGSTOP);
-       constant("_SIGTSTP", SIGTSTP);
-       constant("_SIGCONT", SIGCONT);
-       constant("_SIGTTIN", SIGTTIN);
-       constant("_SIGTTOU", SIGTTOU);
-       constant("_SIGVTALRM", SIGVTALRM);
-       constant("_SIGPROF", SIGPROF);
-       constant("_SIGXCPU", SIGXCPU);
-       constant("_SIGXFSZ", SIGXFSZ);
-       linefeed;
+       COMMENT("Linux signal numbers.");
+       DEFINE(_SIGHUP, SIGHUP);
+       DEFINE(_SIGINT, SIGINT);
+       DEFINE(_SIGQUIT, SIGQUIT);
+       DEFINE(_SIGILL, SIGILL);
+       DEFINE(_SIGTRAP, SIGTRAP);
+       DEFINE(_SIGIOT, SIGIOT);
+       DEFINE(_SIGABRT, SIGABRT);
+       DEFINE(_SIGEMT, SIGEMT);
+       DEFINE(_SIGFPE, SIGFPE);
+       DEFINE(_SIGKILL, SIGKILL);
+       DEFINE(_SIGBUS, SIGBUS);
+       DEFINE(_SIGSEGV, SIGSEGV);
+       DEFINE(_SIGSYS, SIGSYS);
+       DEFINE(_SIGPIPE, SIGPIPE);
+       DEFINE(_SIGALRM, SIGALRM);
+       DEFINE(_SIGTERM, SIGTERM);
+       DEFINE(_SIGUSR1, SIGUSR1);
+       DEFINE(_SIGUSR2, SIGUSR2);
+       DEFINE(_SIGCHLD, SIGCHLD);
+       DEFINE(_SIGPWR, SIGPWR);
+       DEFINE(_SIGWINCH, SIGWINCH);
+       DEFINE(_SIGURG, SIGURG);
+       DEFINE(_SIGIO, SIGIO);
+       DEFINE(_SIGSTOP, SIGSTOP);
+       DEFINE(_SIGTSTP, SIGTSTP);
+       DEFINE(_SIGCONT, SIGCONT);
+       DEFINE(_SIGTTIN, SIGTTIN);
+       DEFINE(_SIGTTOU, SIGTTOU);
+       DEFINE(_SIGVTALRM, SIGVTALRM);
+       DEFINE(_SIGPROF, SIGPROF);
+       DEFINE(_SIGXCPU, SIGXCPU);
+       DEFINE(_SIGXFSZ, SIGXFSZ);
+       BLANK();
 }
 
 void output_irq_cpustat_t_defines(void)
 {
-       text("Linux irq_cpustat_t offsets.");
-       offset("IC_SOFTIRQ_PENDING", irq_cpustat_t, __softirq_pending);
-       size("IC_IRQ_CPUSTAT_T", irq_cpustat_t);
-       linefeed;
+       COMMENT("Linux irq_cpustat_t offsets.");
+       DEFINE(IC_SOFTIRQ_PENDING,
+                       offsetof(irq_cpustat_t, __softirq_pending));
+       DEFINE(IC_IRQ_CPUSTAT_T, sizeof(irq_cpustat_t));
+       BLANK();
 }
index c11b2494bb6ec8d97b1be94f4eef82474885a54e..2ab899c4b4ce1ac38a7b235f5c340af49dcc923c 100644 (file)
@@ -45,8 +45,8 @@ static void __iomem *ioport_map_pci(struct pci_dev *dev,
  */
 void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
 {
-       unsigned long start = pci_resource_start(dev, bar);
-       unsigned long len = pci_resource_len(dev, bar);
+       resource_size_t start = pci_resource_start(dev, bar);
+       resource_size_t len = pci_resource_len(dev, bar);
        unsigned long flags = pci_resource_flags(dev, bar);
 
        if (!len || !start)
index 855977ca51cd3d5e05fd09bec366a40ce687a89b..6537d90a25bbcbd1cc0430a41e2e0d6b46950616 100644 (file)
@@ -143,9 +143,6 @@ void __init plat_time_init(void)
 mips_hpt_frequency = 33000000 * 3 * 5;
 }
 
-/* No other usable initialization hook than this ...  */
-extern void (*late_time_init)(void);
-
 unsigned long ocd_base;
 
 EXPORT_SYMBOL(ocd_base);
index ee2d9f8af5ad53f3d76b49e0ff88b2e80d364e45..2646fcbd7d89d7c09ee72ce7997c808760e9dcdf 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/personality.h>
+#include <linux/kbuild.h>
 #include <asm/ucontext.h>
 #include <asm/processor.h>
 #include <asm/thread_info.h>
 #include "sigframe.h"
 #include "mn10300-serial.h"
 
-#define DEFINE(sym, val) \
-       asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->")
-
-#define OFFSET(sym, str, mem) \
-       DEFINE(sym, offsetof(struct str, mem));
-
 void foo(void)
 {
        OFFSET(SIGCONTEXT_d0, sigcontext, d0);
index dbceae4307dacffd940c035c204a8be972439bf7..c1a8d8f941fdb7d6b11c67007adeb38357ec63e2 100644 (file)
@@ -16,8 +16,8 @@
  */
 void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
 {
-       unsigned long start = pci_resource_start(dev, bar);
-       unsigned long len = pci_resource_len(dev, bar);
+       resource_size_t start = pci_resource_start(dev, bar);
+       resource_size_t len = pci_resource_len(dev, bar);
        unsigned long flags = pci_resource_flags(dev, bar);
 
        if (!len || !start)
index eaa79bc14d9463fcce66b5acc96014d15f9433f4..3efc0b73e4ff9ce71efd7bf93550af12f1710394 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/thread_info.h>
 #include <linux/ptrace.h>
 #include <linux/hardirq.h>
+#include <linux/kbuild.h>
 
 #include <asm/pgtable.h>
 #include <asm/ptrace.h>
 #include <asm/pdc.h>
 #include <asm/uaccess.h>
 
-#define DEFINE(sym, val) \
-       asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : : )
-
 #ifdef CONFIG_64BIT
 #define FRAME_SIZE     128
 #else
index 9448d4e91142a5e62f56afa639de5539d5d28173..ccd61b9567a6e8f837426961ec1c4de231c517f2 100644 (file)
@@ -397,10 +397,9 @@ pcxl_dma_init(void)
                        "pcxl_dma_init: Unable to create gsc /proc dir entry\n");
        else {
                struct proc_dir_entry* ent;
-               ent = create_proc_entry("pcxl_dma", 0, proc_gsc_root);
-               if (ent)
-                       ent->proc_fops = &proc_pcxl_dma_ops;
-               else
+               ent = proc_create("pcxl_dma", 0, proc_gsc_root,
+                                 &proc_pcxl_dma_ops);
+               if (!ent)
                        printk(KERN_WARNING
                                "pci-dma.c: Unable to create pcxl_dma /proc entry.\n");
        }
index f4a811690ab30e1dc4aa9b077c657a8b5ec01faf..9abed07db7fc0ded2b7e041c5e73f65e1911b211 100644 (file)
@@ -438,8 +438,8 @@ void ioport_unmap(void __iomem *addr)
 /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
 void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
 {
-       unsigned long start = pci_resource_start(dev, bar);
-       unsigned long len = pci_resource_len(dev, bar);
+       resource_size_t start = pci_resource_start(dev, bar);
+       resource_size_t len = pci_resource_len(dev, bar);
        unsigned long flags = pci_resource_flags(dev, bar);
 
        if (!len || !start)
index af1d2c894ee1a2980010ec8552de674e78e6b6d3..ec9228d687b08515319694001c6c1feffb577944 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/time.h>
 #include <linux/hardirq.h>
 #endif
+#include <linux/kbuild.h>
 
 #include <asm/io.h>
 #include <asm/page.h>
 #include <asm/iseries/alpaca.h>
 #endif
 
-#define DEFINE(sym, val) \
-       asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : : )
-
 int main(void)
 {
        DEFINE(THREAD, offsetof(struct task_struct, thread));
index 1ffacc698ffb613b3614d666e5f41f15511743bd..1e656b43ad7fb87f45a71c393e9f96ea5e18a504 100644 (file)
@@ -591,10 +591,8 @@ int __init lparcfg_init(void)
                        !firmware_has_feature(FW_FEATURE_ISERIES))
                mode |= S_IWUSR;
 
-       ent = create_proc_entry("ppc64/lparcfg", mode, NULL);
-       if (ent) {
-               ent->proc_fops = &lparcfg_fops;
-       } else {
+       ent = proc_create("ppc64/lparcfg", mode, NULL, &lparcfg_fops);
+       if (!ent) {
                printk(KERN_ERR "Failed to create ppc64/lparcfg\n");
                return -EIO;
        }
index 09fcb50c45aec30647df4eb6650b4ec380f43d2a..cf6b5a7d8b3f764668fed2dbd0f4e3015269493f 100644 (file)
@@ -133,9 +133,6 @@ EXPORT_SYMBOL(adb_try_handler_change);
 EXPORT_SYMBOL(cuda_request);
 EXPORT_SYMBOL(cuda_poll);
 #endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_VT
-EXPORT_SYMBOL(kd_mksound);
-#endif
 EXPORT_SYMBOL(to_tm);
 
 #ifdef CONFIG_PPC32
index f78dfce1b771241256d4242c328286cbc3c92a8a..c647ddef40dc4dcf12865f834869101fa9bfb6da 100644 (file)
@@ -68,12 +68,11 @@ static int __init proc_ppc64_init(void)
 {
        struct proc_dir_entry *pde;
 
-       pde = create_proc_entry("ppc64/systemcfg", S_IFREG|S_IRUGO, NULL);
+       pde = proc_create_data("ppc64/systemcfg", S_IFREG|S_IRUGO, NULL,
+                              &page_map_fops, vdso_data);
        if (!pde)
                return 1;
-       pde->data = vdso_data;
        pde->size = PAGE_SIZE;
-       pde->proc_fops = &page_map_fops;
 
        return 0;
 }
index f2e3bc714d7695834971e627f2c89368c8798755..f9c6abc84a9483a9fce2fb496642ec863f369fa3 100644 (file)
@@ -255,8 +255,6 @@ static void check_location(struct seq_file *m, const char *c);
 
 static int __init proc_rtas_init(void)
 {
-       struct proc_dir_entry *entry;
-
        if (!machine_is(pseries))
                return -ENODEV;
 
@@ -264,35 +262,20 @@ static int __init proc_rtas_init(void)
        if (rtas_node == NULL)
                return -ENODEV;
 
-       entry = create_proc_entry("ppc64/rtas/progress", S_IRUGO|S_IWUSR, NULL);
-       if (entry)
-               entry->proc_fops = &ppc_rtas_progress_operations;
-
-       entry = create_proc_entry("ppc64/rtas/clock", S_IRUGO|S_IWUSR, NULL);
-       if (entry)
-               entry->proc_fops = &ppc_rtas_clock_operations;
-
-       entry = create_proc_entry("ppc64/rtas/poweron", S_IWUSR|S_IRUGO, NULL);
-       if (entry)
-               entry->proc_fops = &ppc_rtas_poweron_operations;
-
-       entry = create_proc_entry("ppc64/rtas/sensors", S_IRUGO, NULL);
-       if (entry)
-               entry->proc_fops = &ppc_rtas_sensors_operations;
-
-       entry = create_proc_entry("ppc64/rtas/frequency", S_IWUSR|S_IRUGO,
-                                 NULL);
-       if (entry)
-               entry->proc_fops = &ppc_rtas_tone_freq_operations;
-
-       entry = create_proc_entry("ppc64/rtas/volume", S_IWUSR|S_IRUGO, NULL);
-       if (entry)
-               entry->proc_fops = &ppc_rtas_tone_volume_operations;
-
-       entry = create_proc_entry("ppc64/rtas/rmo_buffer", S_IRUSR, NULL);
-       if (entry)
-               entry->proc_fops = &ppc_rtas_rmo_buf_ops;
-
+       proc_create("ppc64/rtas/progress", S_IRUGO|S_IWUSR, NULL,
+                   &ppc_rtas_progress_operations);
+       proc_create("ppc64/rtas/clock", S_IRUGO|S_IWUSR, NULL,
+                   &ppc_rtas_clock_operations);
+       proc_create("ppc64/rtas/poweron", S_IWUSR|S_IRUGO, NULL,
+                   &ppc_rtas_poweron_operations);
+       proc_create("ppc64/rtas/sensors", S_IRUGO, NULL,
+                   &ppc_rtas_sensors_operations);
+       proc_create("ppc64/rtas/frequency", S_IWUSR|S_IRUGO, NULL,
+                   &ppc_rtas_tone_freq_operations);
+       proc_create("ppc64/rtas/volume", S_IWUSR|S_IRUGO, NULL,
+                   &ppc_rtas_tone_volume_operations);
+       proc_create("ppc64/rtas/rmo_buffer", S_IRUSR, NULL,
+                   &ppc_rtas_rmo_buf_ops);
        return 0;
 }
 
index 627f126d1848b4ec1f5e0eb2e2d8c5870bda93c5..0a5e22b22729f6b70443c1b0c9fb622aca4ea26e 100644 (file)
@@ -704,18 +704,11 @@ static int initialize_flash_pde_data(const char *rtas_call_name,
 static struct proc_dir_entry *create_flash_pde(const char *filename,
                                               const struct file_operations *fops)
 {
-       struct proc_dir_entry *ent = NULL;
-
-       ent = create_proc_entry(filename, S_IRUSR | S_IWUSR, NULL);
-       if (ent != NULL) {
-               ent->proc_fops = fops;
-               ent->owner = THIS_MODULE;
-       }
-
-       return ent;
+       return proc_create(filename, S_IRUSR | S_IWUSR, NULL, fops);
 }
 
 static const struct file_operations rtas_flash_operations = {
+       .owner          = THIS_MODULE,
        .read           = rtas_flash_read,
        .write          = rtas_flash_write,
        .open           = rtas_excl_open,
@@ -723,6 +716,7 @@ static const struct file_operations rtas_flash_operations = {
 };
 
 static const struct file_operations manage_flash_operations = {
+       .owner          = THIS_MODULE,
        .read           = manage_flash_read,
        .write          = manage_flash_write,
        .open           = rtas_excl_open,
@@ -730,6 +724,7 @@ static const struct file_operations manage_flash_operations = {
 };
 
 static const struct file_operations validate_flash_operations = {
+       .owner          = THIS_MODULE,
        .read           = validate_flash_read,
        .write          = validate_flash_write,
        .open           = rtas_excl_open,
index 62280c292aac88b481291757a7e78aa094c3cf8f..7298e7db2c8365cf83f8519350f917a01a35c8c3 100644 (file)
@@ -1065,10 +1065,9 @@ int __init spu_sched_init(void)
 
        mod_timer(&spuloadavg_timer, 0);
 
-       entry = create_proc_entry("spu_loadavg", 0, NULL);
+       entry = proc_create("spu_loadavg", 0, NULL, &spu_loadavg_fops);
        if (!entry)
                goto out_stop_kthread;
-       entry->proc_fops = &spu_loadavg_fops;
 
        pr_debug("spusched: tick: %d, min ticks: %d, default ticks: %d\n",
                        SPUSCHED_TICK, MIN_SPU_TIMESLICE, DEF_SPU_TIMESLICE);
index b9c79eda3359bb083bf8b0da8cf5763f3a58ccab..53202422ba727c8ec9a9f95a80fb1db95181e12c 100644 (file)
@@ -201,10 +201,9 @@ static int __init sputrace_init(void)
        if (!sputrace_log)
                goto out;
 
-       entry = create_proc_entry("sputrace", S_IRUSR, NULL);
+       entry = proc_create("sputrace", S_IRUSR, NULL, &sputrace_fops);
        if (!entry)
                goto out_free_log;
-       entry->proc_fops = &sputrace_fops;
 
        for (i = 0; i < ARRAY_SIZE(spu_probes); i++) {
                struct spu_probe *p = &spu_probes[i];
index e5b40e3e0082cfd07c1597edd26c6f5ebbac54f5..b0f8a857ec02d356d1f4a88f8e21cfbcd8b4f66f 100644 (file)
@@ -330,15 +330,11 @@ static const struct file_operations proc_lpevents_operations = {
 
 static int __init proc_lpevents_init(void)
 {
-       struct proc_dir_entry *e;
-
        if (!firmware_has_feature(FW_FEATURE_ISERIES))
                return 0;
 
-       e = create_proc_entry("iSeries/lpevents", S_IFREG|S_IRUGO, NULL);
-       if (e)
-               e->proc_fops = &proc_lpevents_operations;
-
+       proc_create("iSeries/lpevents", S_IFREG|S_IRUGO, NULL,
+                   &proc_lpevents_operations);
        return 0;
 }
 __initcall(proc_lpevents_init);
index c0f2433bc16e75c20532982c65e581902b0e5481..1dc7295746dac6471503b098182c9f1e128239d8 100644 (file)
@@ -1255,11 +1255,11 @@ static int __init mf_proc_init(void)
                if (i == 3)     /* no vmlinux entry for 'D' */
                        continue;
 
-               ent = create_proc_entry("vmlinux", S_IFREG|S_IWUSR, mf);
+               ent = proc_create_data("vmlinux", S_IFREG|S_IWUSR, mf,
+                                      &proc_vmlinux_operations,
+                                      (void *)(long)i);
                if (!ent)
                        return 1;
-               ent->data = (void *)(long)i;
-               ent->proc_fops = &proc_vmlinux_operations;
        }
 
        ent = create_proc_entry("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root);
index f2cde4180204c6559d0229b156f5440a97c43bb0..91f4c6cd4b9936fea9635b14e30f48b858a657c8 100644 (file)
@@ -110,15 +110,11 @@ static const struct file_operations proc_titantod_operations = {
 
 static int __init iseries_proc_init(void)
 {
-       struct proc_dir_entry *e;
-
        if (!firmware_has_feature(FW_FEATURE_ISERIES))
                return 0;
 
-       e = create_proc_entry("iSeries/titanTod", S_IFREG|S_IRUGO, NULL);
-       if (e)
-               e->proc_fops = &proc_titantod_operations;
-
+       proc_create("iSeries/titanTod", S_IFREG|S_IRUGO, NULL,
+                   &proc_titantod_operations);
        return 0;
 }
 __initcall(iseries_proc_init);
index df23331eb25c2416b99fd91c137fa62675c7bbb8..49ff4dc422b7be7b0bf8565335d48cb34cc0979f 100644 (file)
@@ -180,15 +180,10 @@ static const struct file_operations proc_viopath_operations = {
 
 static int __init vio_proc_init(void)
 {
-       struct proc_dir_entry *e;
-
        if (!firmware_has_feature(FW_FEATURE_ISERIES))
                return 0;
 
-       e = create_proc_entry("iSeries/config", 0, NULL);
-       if (e)
-               e->proc_fops = &proc_viopath_operations;
-
+       proc_create("iSeries/config", 0, NULL, &proc_viopath_operations);
         return 0;
 }
 __initcall(vio_proc_init);
index a3fd56b186e6063284306e37339a9a7cc7f8349d..6f544ba4b37feebfdd0be835b4cbf397c74783de 100644 (file)
@@ -1259,14 +1259,8 @@ static const struct file_operations proc_eeh_operations = {
 
 static int __init eeh_init_proc(void)
 {
-       struct proc_dir_entry *e;
-
-       if (machine_is(pseries)) {
-               e = create_proc_entry("ppc64/eeh", 0, NULL);
-               if (e)
-                       e->proc_fops = &proc_eeh_operations;
-       }
-
+       if (machine_is(pseries))
+               proc_create("ppc64/eeh", 0, NULL, &proc_eeh_operations);
        return 0;
 }
 __initcall(eeh_init_proc);
index ac75c10de27842a967cfc3bc4d9333840d055e2f..75769aae41d5ec7e67ee31dfc5b552971a7b1f77 100644 (file)
@@ -512,12 +512,9 @@ static int proc_ppc64_create_ofdt(void)
        if (!machine_is(pseries))
                return 0;
 
-       ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL);
-       if (ent) {
-               ent->data = NULL;
+       ent = proc_create("ppc64/ofdt", S_IWUSR, NULL, &ofdt_fops);
+       if (ent)
                ent->size = 0;
-               ent->proc_fops = &ofdt_fops;
-       }
 
        return 0;
 }
index befadd4f9524880d197240836557369a5386a487..7d3e2b0bd4d299d5f467fde2a014dec0fb835fdb 100644 (file)
@@ -468,10 +468,9 @@ static int __init rtas_init(void)
                return -ENOMEM;
        }
 
-       entry = create_proc_entry("ppc64/rtas/error_log", S_IRUSR, NULL);
-       if (entry)
-               entry->proc_fops = &proc_rtas_log_operations;
-       else
+       entry = proc_create("ppc64/rtas/error_log", S_IRUSR, NULL,
+                           &proc_rtas_log_operations);
+       if (!entry)
                printk(KERN_ERR "Failed to create error_log proc entry\n");
 
        if (kernel_thread(rtasd, NULL, CLONE_FS) < 0)
index 7b45670c7af387c34d670018dcc76108958d45fb..324c01b70dddfc14701210dc1547c3dfd9a65fab 100644 (file)
@@ -418,22 +418,21 @@ arch_initcall(gfar_of_init);
 #include <linux/i2c.h>
 struct i2c_driver_device {
        char    *of_device;
-       char    *i2c_driver;
        char    *i2c_type;
 };
 
 static struct i2c_driver_device i2c_devices[] __initdata = {
-       {"ricoh,rs5c372a", "rtc-rs5c372", "rs5c372a",},
-       {"ricoh,rs5c372b", "rtc-rs5c372", "rs5c372b",},
-       {"ricoh,rv5c386",  "rtc-rs5c372", "rv5c386",},
-       {"ricoh,rv5c387a", "rtc-rs5c372", "rv5c387a",},
-       {"dallas,ds1307",  "rtc-ds1307",  "ds1307",},
-       {"dallas,ds1337",  "rtc-ds1307",  "ds1337",},
-       {"dallas,ds1338",  "rtc-ds1307",  "ds1338",},
-       {"dallas,ds1339",  "rtc-ds1307",  "ds1339",},
-       {"dallas,ds1340",  "rtc-ds1307",  "ds1340",},
-       {"stm,m41t00",     "rtc-ds1307",  "m41t00"},
-       {"dallas,ds1374",  "rtc-ds1374",  "rtc-ds1374",},
+       {"ricoh,rs5c372a", "rs5c372a"},
+       {"ricoh,rs5c372b", "rs5c372b"},
+       {"ricoh,rv5c386",  "rv5c386"},
+       {"ricoh,rv5c387a", "rv5c387a"},
+       {"dallas,ds1307",  "ds1307"},
+       {"dallas,ds1337",  "ds1337"},
+       {"dallas,ds1338",  "ds1338"},
+       {"dallas,ds1339",  "ds1339"},
+       {"dallas,ds1340",  "ds1340"},
+       {"stm,m41t00",     "m41t00"},
+       {"dallas,ds1374",  "rtc-ds1374"},
 };
 
 static int __init of_find_i2c_driver(struct device_node *node,
@@ -444,9 +443,7 @@ static int __init of_find_i2c_driver(struct device_node *node,
        for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) {
                if (!of_device_is_compatible(node, i2c_devices[i].of_device))
                        continue;
-               if (strlcpy(info->driver_name, i2c_devices[i].i2c_driver,
-                           KOBJ_NAME_LEN) >= KOBJ_NAME_LEN ||
-                   strlcpy(info->type, i2c_devices[i].i2c_type,
+               if (strlcpy(info->type, i2c_devices[i].i2c_type,
                            I2C_NAME_SIZE) >= I2C_NAME_SIZE)
                        return -ENOMEM;
                return 0;
index a51a17714231ea2c7cc3f168950a4a88df726d7e..8dcbdd6c2d2c3bae19ef6f846f2f4b25b26c6c58 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/suspend.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
+#include <linux/kbuild.h>
+
 #include <asm/io.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/thread_info.h>
 #include <asm/vdso_datapage.h>
 
-#define DEFINE(sym, val) \
-       asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : : )
-
 int
 main(void)
 {
index 50ce83f20adb75ff54f6b4830fdec1ea13b9298d..df3ef6db072c806b7295449ddf70a78499a6258c 100644 (file)
@@ -1121,8 +1121,8 @@ void __init pci_init_resource(struct resource *res, resource_size_t start,
 
 void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
 {
-       unsigned long start = pci_resource_start(dev, bar);
-       unsigned long len = pci_resource_len(dev, bar);
+       resource_size_t start = pci_resource_start(dev, bar);
+       resource_size_t len = pci_resource_len(dev, bar);
        unsigned long flags = pci_resource_flags(dev, bar);
 
        if (!len)
index d9036ef0b6581215211397cd806f10eae4acfe38..16ac11ca7ba0feb0b022fc8093a21bcf6cae4f61 100644 (file)
@@ -183,9 +183,6 @@ EXPORT_SYMBOL(cuda_poll);
 #if defined(CONFIG_BOOTX_TEXT)
 EXPORT_SYMBOL(btext_update_display);
 #endif
-#ifdef CONFIG_VT
-EXPORT_SYMBOL(kd_mksound);
-#endif
 EXPORT_SYMBOL(to_tm);
 
 EXPORT_SYMBOL(pm_power_off);
index 0df6aacb8237e5429e1af92ba0e06284d25181cd..24f6e0694ac1499d5e28dba98772ac4bb17fe94e 100644 (file)
@@ -30,8 +30,6 @@ static void (*callback_init_IRQ)(void);
 
 extern unsigned char __res[sizeof(bd_t)];
 
-extern void (*late_time_init)(void);
-
 #ifdef CONFIG_GEN_RTC
 TODC_ALLOC();
 
index 1375f8a4469e8e89d56fadba47e9992fbcee6963..fa28ecae636b2237a8bfddb49f05851ef7056f9c 100644 (file)
@@ -5,44 +5,38 @@
  */
 
 #include <linux/sched.h>
-
-/* Use marker if you need to separate the values later */
-
-#define DEFINE(sym, val, marker) \
-       asm volatile("\n->" #sym " %0 " #val " " #marker : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : : )
+#include <linux/kbuild.h>
 
 int main(void)
 {
-       DEFINE(__THREAD_info, offsetof(struct task_struct, stack),);
-       DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp),);
-       DEFINE(__THREAD_per, offsetof(struct task_struct, thread.per_info),);
+       DEFINE(__THREAD_info, offsetof(struct task_struct, stack));
+       DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp));
+       DEFINE(__THREAD_per, offsetof(struct task_struct, thread.per_info));
        DEFINE(__THREAD_mm_segment,
-              offsetof(struct task_struct, thread.mm_segment),);
+              offsetof(struct task_struct, thread.mm_segment));
        BLANK();
-       DEFINE(__TASK_pid, offsetof(struct task_struct, pid),);
+       DEFINE(__TASK_pid, offsetof(struct task_struct, pid));
        BLANK();
-       DEFINE(__PER_atmid, offsetof(per_struct, lowcore.words.perc_atmid),);
-       DEFINE(__PER_address, offsetof(per_struct, lowcore.words.address),);
-       DEFINE(__PER_access_id, offsetof(per_struct, lowcore.words.access_id),);
+       DEFINE(__PER_atmid, offsetof(per_struct, lowcore.words.perc_atmid));
+       DEFINE(__PER_address, offsetof(per_struct, lowcore.words.address));
+       DEFINE(__PER_access_id, offsetof(per_struct, lowcore.words.access_id));
        BLANK();
-       DEFINE(__TI_task, offsetof(struct thread_info, task),);
-       DEFINE(__TI_domain, offsetof(struct thread_info, exec_domain),);
-       DEFINE(__TI_flags, offsetof(struct thread_info, flags),);
-       DEFINE(__TI_cpu, offsetof(struct thread_info, cpu),);
-       DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count),);
+       DEFINE(__TI_task, offsetof(struct thread_info, task));
+       DEFINE(__TI_domain, offsetof(struct thread_info, exec_domain));
+       DEFINE(__TI_flags, offsetof(struct thread_info, flags));
+       DEFINE(__TI_cpu, offsetof(struct thread_info, cpu));
+       DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count));
        BLANK();
-       DEFINE(__PT_ARGS, offsetof(struct pt_regs, args),);
-       DEFINE(__PT_PSW, offsetof(struct pt_regs, psw),);
-       DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs),);
-       DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2),);
-       DEFINE(__PT_ILC, offsetof(struct pt_regs, ilc),);
-       DEFINE(__PT_TRAP, offsetof(struct pt_regs, trap),);
-       DEFINE(__PT_SIZE, sizeof(struct pt_regs),);
+       DEFINE(__PT_ARGS, offsetof(struct pt_regs, args));
+       DEFINE(__PT_PSW, offsetof(struct pt_regs, psw));
+       DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs));
+       DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2));
+       DEFINE(__PT_ILC, offsetof(struct pt_regs, ilc));
+       DEFINE(__PT_TRAP, offsetof(struct pt_regs, trap));
+       DEFINE(__PT_SIZE, sizeof(struct pt_regs));
        BLANK();
-       DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain),);
-       DEFINE(__SF_GPRS, offsetof(struct stack_frame, gprs),);
-       DEFINE(__SF_EMPTY, offsetof(struct stack_frame, empty1),);
+       DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain));
+       DEFINE(__SF_GPRS, offsetof(struct stack_frame, gprs));
+       DEFINE(__SF_EMPTY, offsetof(struct stack_frame, empty1));
        return 0;
 }
index 6766e37fe8ea01955da640895bd2068358f660d6..bdbb3bcd78a5d7088ed4cfd39f7fb444e2f15814 100644 (file)
@@ -49,9 +49,9 @@ SP_ILC             =  STACK_FRAME_OVERHEAD + __PT_ILC
 SP_TRAP      = STACK_FRAME_OVERHEAD + __PT_TRAP
 SP_SIZE      = STACK_FRAME_OVERHEAD + __PT_SIZE
 
-_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
+_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
                 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
-_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
+_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
                 _TIF_MCCK_PENDING)
 
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
@@ -316,7 +316,7 @@ sysc_work:
        bo      BASED(sysc_mcck_pending)
        tm      __TI_flags+3(%r9),_TIF_NEED_RESCHED
        bo      BASED(sysc_reschedule)
-       tm      __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
+       tm      __TI_flags+3(%r9),_TIF_SIGPENDING
        bnz     BASED(sysc_sigpending)
        tm      __TI_flags+3(%r9),_TIF_RESTART_SVC
        bo      BASED(sysc_restart)
@@ -342,7 +342,7 @@ sysc_mcck_pending:
        br      %r1                     # TIF bit will be cleared by handler
 
 #
-# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
+# _TIF_SIGPENDING is set, call do_signal
 #
 sysc_sigpending:
        ni      __TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
@@ -657,7 +657,7 @@ io_work:
        lr      %r15,%r1
 #
 # One of the work bits is on. Find out which one.
-# Checked are: _TIF_SIGPENDING, _TIF_RESTORE_SIGMASK, _TIF_NEED_RESCHED
+# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED
 #              and _TIF_MCCK_PENDING
 #
 io_work_loop:
@@ -665,7 +665,7 @@ io_work_loop:
        bo      BASED(io_mcck_pending)
        tm      __TI_flags+3(%r9),_TIF_NEED_RESCHED
        bo      BASED(io_reschedule)
-       tm      __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
+       tm      __TI_flags+3(%r9),_TIF_SIGPENDING
        bnz     BASED(io_sigpending)
        b       BASED(io_restore)
 io_work_done:
@@ -693,7 +693,7 @@ io_reschedule:
        b       BASED(io_work_loop)
 
 #
-# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
+# _TIF_SIGPENDING is set, call do_signal
 #
 io_sigpending:
        TRACE_IRQS_ON
index cd959c0b2e16b4cd225429e960cf2a96e4b7276a..5a4a7bcd2bbad8e92e95eb529fb11559977c0dd9 100644 (file)
@@ -52,9 +52,9 @@ SP_SIZE      =        STACK_FRAME_OVERHEAD + __PT_SIZE
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
 
-_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
+_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
                 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
-_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
+_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
                 _TIF_MCCK_PENDING)
 
 #define BASED(name) name-system_call(%r13)
@@ -308,7 +308,7 @@ sysc_work:
        jo      sysc_mcck_pending
        tm      __TI_flags+7(%r9),_TIF_NEED_RESCHED
        jo      sysc_reschedule
-       tm      __TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
+       tm      __TI_flags+7(%r9),_TIF_SIGPENDING
        jnz     sysc_sigpending
        tm      __TI_flags+7(%r9),_TIF_RESTART_SVC
        jo      sysc_restart
@@ -332,7 +332,7 @@ sysc_mcck_pending:
        jg      s390_handle_mcck        # TIF bit will be cleared by handler
 
 #
-# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
+# _TIF_SIGPENDING is set, call do_signal
 #
 sysc_sigpending:
        ni      __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
@@ -648,7 +648,7 @@ io_work_loop:
        jo      io_mcck_pending
        tm      __TI_flags+7(%r9),_TIF_NEED_RESCHED
        jo      io_reschedule
-       tm      __TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
+       tm      __TI_flags+7(%r9),_TIF_SIGPENDING
        jnz     io_sigpending
        j       io_restore
 io_work_done:
@@ -674,7 +674,7 @@ io_reschedule:
        j       io_work_loop
 
 #
-# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
+# _TIF_SIGPENDING or is set, call do_signal
 #
 io_sigpending:
        TRACE_IRQS_ON
index c36d8123ca14bd464b2cfb59b2c3c9eb0498ca6d..c59a86dca5849617ac74428647fe3ddb7834937e 100644 (file)
@@ -60,8 +60,6 @@ init_IRQ(void)
 /*
  * Switch to the asynchronous interrupt stack for softirq execution.
  */
-extern void __do_softirq(void);
-
 asmlinkage void do_softirq(void)
 {
        unsigned long flags, old, new;
index 00d52a20d8a59425105f0307aa227d66b4871308..e7c150d4970297629be13c17fefa543f5cfe9ac5 100644 (file)
@@ -199,8 +199,7 @@ static struct platform_device *migor_devices[] __initdata = {
 
 static struct i2c_board_info __initdata migor_i2c_devices[] = {
        {
-               I2C_BOARD_INFO("rtc-rs5c372", 0x32),
-               .type   = "rs5c372b",
+               I2C_BOARD_INFO("rs5c372b", 0x32),
        },
        {
                I2C_BOARD_INFO("migor_ts", 0x51),
index a5c5e92365011bfd7f1ba4594b0fb26f1c116540..ac0a96522e45e3f9387ae578149fe9ec05e34578 100644 (file)
@@ -199,8 +199,7 @@ static struct platform_device smbus_device = {
 
 static struct i2c_board_info __initdata highlander_i2c_devices[] = {
        {
-               I2C_BOARD_INFO("rtc-rs5c372", 0x32),
-               .type   = "r2025sd",
+               I2C_BOARD_INFO("r2025sd", 0x32),
        },
 };
 
index 49b435c3a57a382302f97e8977954ee510c0aab3..08d2e7325252a19071fe446055417bd4d5368dd3 100644 (file)
@@ -191,8 +191,8 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
 
 void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
 {
-       unsigned long start = pci_resource_start(dev, bar);
-       unsigned long len = pci_resource_len(dev, bar);
+       resource_size_t start = pci_resource_start(dev, bar);
+       resource_size_t len = pci_resource_len(dev, bar);
        unsigned long flags = pci_resource_flags(dev, bar);
 
        if (unlikely(!len || !start))
index dc6725c51a8971e4071897636ff60ec6214ac387..57cf0e0680f36b3e4b397d16979ec2f53c36df40 100644 (file)
 #include <linux/stddef.h>
 #include <linux/types.h>
 #include <linux/mm.h>
-#include <asm/thread_info.h>
-
-#define DEFINE(sym, val) \
-        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+#include <linux/kbuild.h>
 
-#define BLANK() asm volatile("\n->" : : )
+#include <asm/thread_info.h>
 
 int main(void)
 {
index 9bf19b00696ac5ae6ad0456e1a3ec981f1d0b53d..a2a99e487e33af4c6c1714f0d36e9065556f701a 100644 (file)
@@ -200,8 +200,6 @@ void irq_ctx_exit(int cpu)
        hardirq_ctx[cpu] = NULL;
 }
 
-extern asmlinkage void __do_softirq(void);
-
 asmlinkage void do_softirq(void)
 {
        unsigned long flags;
index 6773ed76e414bec7b851d94cebddf2fec48ff1e7..cd3f7694e9b9240e20455a5cb3933c1a343b0f3b 100644 (file)
 
 #include <linux/sched.h>
 // #include <linux/mm.h>
-
-#define DEFINE(sym, val) \
-       asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : : )
+#include <linux/kbuild.h>
 
 int foo(void)
 {
index 0bcf98a7ef389b83f0ae4fb937823864a776f221..aa8ee06cf488b1f3de617df99faf0949d49cef0a 100644 (file)
@@ -282,3 +282,5 @@ EXPORT_SYMBOL(do_BUG);
 
 /* Sun Power Management Idle Handler */
 EXPORT_SYMBOL(pm_idle);
+
+EXPORT_SYMBOL(empty_zero_page);
index 54501c1ca785c00b10e11801a6fa240e6eec9341..9ef37e13a920e28ba99e197dc50dff7b812c5972 100644 (file)
@@ -21,8 +21,8 @@ EXPORT_SYMBOL(ioport_unmap);
 /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
 void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
 {
-       unsigned long start = pci_resource_start(dev, bar);
-       unsigned long len = pci_resource_len(dev, bar);
+       resource_size_t start = pci_resource_start(dev, bar);
+       resource_size_t len = pci_resource_len(dev, bar);
        unsigned long flags = pci_resource_flags(dev, bar);
 
        if (!len || !start)
index ac556db06973a12297c8cc9e3845d22da787b40c..7120ebbd4d039020e058cce8fe46c1e3c71418b3 100644 (file)
@@ -21,8 +21,8 @@ EXPORT_SYMBOL(ioport_unmap);
 /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
 void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
 {
-       unsigned long start = pci_resource_start(dev, bar);
-       unsigned long len = pci_resource_len(dev, bar);
+       resource_size_t start = pci_resource_start(dev, bar);
+       resource_size_t len = pci_resource_len(dev, bar);
        unsigned long flags = pci_resource_flags(dev, bar);
 
        if (!len || !start)
index 8c2b50e8abc63d7696386f96d0ce06c62003c1fc..4cad0b32b0afcd5256dce395a1ce6e682c50715c 100644 (file)
@@ -160,6 +160,7 @@ extern unsigned int sparc_ramdisk_image;
 extern unsigned int sparc_ramdisk_size;
 
 struct page *mem_map_zero __read_mostly;
+EXPORT_SYMBOL(mem_map_zero);
 
 unsigned int sparc64_highest_unlocked_tlb_ent __read_mostly;
 
index 984f80e668ca5d7c85b3f8ae549dc13fa5aabe57..6540d2c9fbb76f684db03539e26e202178cf18f5 100644 (file)
@@ -59,7 +59,7 @@ static int make_proc_exitcode(void)
 {
        struct proc_dir_entry *ent;
 
-       ent = create_proc_entry("exitcode", 0600, &proc_root);
+       ent = create_proc_entry("exitcode", 0600, NULL);
        if (ent == NULL) {
                printk(KERN_WARNING "make_proc_exitcode : Failed to register "
                       "/proc/exitcode\n");
index e8cb9ff183e9fe1da41020bc39ffe22b43ef56c7..83603cfbde819ce736a034d414361ea71c24cca7 100644 (file)
@@ -364,7 +364,7 @@ int __init make_proc_sysemu(void)
        if (!sysemu_supported)
                return 0;
 
-       ent = create_proc_entry("sysemu", 0600, &proc_root);
+       ent = create_proc_entry("sysemu", 0600, NULL);
 
        if (ent == NULL)
        {
index e066e84493b129a23f7018ce09d145dddf14f97b..0d0cea2ac98d5df30a308aa4468b14db3f7f681b 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <linux/clockchips.h>
+#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/jiffies.h>
 #include <linux/threads.h>
@@ -109,8 +110,6 @@ static void __init setup_itimer(void)
        clockevents_register_device(&itimer_clockevent);
 }
 
-extern void (*late_time_init)(void);
-
 void __init time_init(void)
 {
        long long nsecs;
index cee5c3142d41c41644341e62a5acb86f6247aa9b..581e6986a7767cc994b1a09e9a7f529a2c25ad01 100644 (file)
 #include <linux/kernel_stat.h>
 #include <linux/ptrace.h>
 #include <linux/hardirq.h>
+#include <linux/kbuild.h>
+
 #include <asm/irq.h>
 #include <asm/errno.h>
 
-#define DEFINE(sym, val) \
-       asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : : )
-
 int main (void)
 {
        /* offsets into the task struct */
index 7165478824e7405757536e65d04d493d281d762c..687e367d8b64c81e39a99632e87d012e1c8015b5 100644 (file)
@@ -790,8 +790,8 @@ pci_free_consistent (struct pci_dev *pdev, size_t size, void *cpu_addr,
 
 void __iomem *pci_iomap (struct pci_dev *dev, int bar, unsigned long max)
 {
-       unsigned long start = pci_resource_start (dev, bar);
-       unsigned long len = pci_resource_len (dev, bar);
+       resource_size_t start = pci_resource_start (dev, bar);
+       resource_size_t len = pci_resource_len (dev, bar);
 
        if (!start || len == 0)
                return 0;
index a12dbb2b93f381066a34ec0ff57e5ff753ba29b5..f70e3e3a9fa78ca0649adccf695ad8df40ade0e3 100644 (file)
@@ -537,9 +537,6 @@ config CALGARY_IOMMU_ENABLED_BY_DEFAULT
          Calgary anyway, pass 'iommu=calgary' on the kernel command line.
          If unsure, say Y.
 
-config IOMMU_HELPER
-       def_bool (CALGARY_IOMMU || GART_IOMMU)
-
 # need this always selected by IOMMU for the VIA workaround
 config SWIOTLB
        bool
@@ -550,6 +547,8 @@ config SWIOTLB
          access 32-bits of memory can be used on systems with more than
          3 GB of memory. If unsure, say Y.
 
+config IOMMU_HELPER
+       def_bool (CALGARY_IOMMU || GART_IOMMU || SWIOTLB)
 
 config NR_CPUS
        int "Maximum number of CPUs (2-255)"
@@ -1505,6 +1504,10 @@ config PCI_GODIRECT
 config PCI_GOANY
        bool "Any"
 
+config PCI_GOOLPC
+       bool "OLPC"
+       depends on OLPC
+
 endchoice
 
 config PCI_BIOS
@@ -1514,12 +1517,17 @@ config PCI_BIOS
 # x86-64 doesn't support PCI BIOS access from long mode so always go direct.
 config PCI_DIRECT
        def_bool y
-       depends on PCI && (X86_64 || (PCI_GODIRECT || PCI_GOANY) || X86_VISWS)
+       depends on PCI && (X86_64 || (PCI_GODIRECT || PCI_GOANY || PCI_GOOLPC) || X86_VISWS)
 
 config PCI_MMCONFIG
        def_bool y
        depends on X86_32 && PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
 
+config PCI_OLPC
+       bool
+       depends on PCI && PCI_GOOLPC
+       default y
+
 config PCI_DOMAINS
        def_bool y
        depends on PCI
@@ -1639,6 +1647,13 @@ config GEODE_MFGPT_TIMER
          MFGPTs have a better resolution and max interval than the
          generic PIT, and are suitable for use as high-res timers.
 
+config OLPC
+       bool "One Laptop Per Child support"
+       default n
+       help
+         Add support for detecting the unique features of the OLPC
+         XO hardware.
+
 endif # X86_32
 
 config K8_NB
index d84a48ece78503b10e8429981e44397b6755a454..03399d64013b21459f63942c06bc6c33b803f425 100644 (file)
@@ -126,17 +126,25 @@ void query_edd(void)
 {
        char eddarg[8];
        int do_mbr = 1;
+#ifdef CONFIG_EDD_OFF
+       int do_edd = 0;
+#else
        int do_edd = 1;
+#endif
        int be_quiet;
        int devno;
        struct edd_info ei, *edp;
        u32 *mbrptr;
 
        if (cmdline_find_option("edd", eddarg, sizeof eddarg) > 0) {
-               if (!strcmp(eddarg, "skipmbr") || !strcmp(eddarg, "skip"))
+               if (!strcmp(eddarg, "skipmbr") || !strcmp(eddarg, "skip")) {
+                       do_edd = 1;
                        do_mbr = 0;
+               }
                else if (!strcmp(eddarg, "off"))
                        do_edd = 0;
+               else if (!strcmp(eddarg, "on"))
+                       do_edd = 1;
        }
 
        be_quiet = cmdline_find_option_bool("quiet");
index bbed3a26ce5567abb107f0371651c906b5f368a7..cb3856a18c8544e1ffe722d33a7713439043829d 100644 (file)
@@ -128,7 +128,7 @@ asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
 
        current->state = TASK_INTERRUPTIBLE;
        schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
+       set_restore_sigmask();
        return -ERESTARTNOHAND;
 }
 
index fa19c3819540d0f823bd675f61457bab2fc31b30..30d54ed27e558cb1d3725f38c411e820b7fe5073 100644 (file)
@@ -91,6 +91,8 @@ endif
 obj-$(CONFIG_SCx200)           += scx200.o
 scx200-y                       += scx200_32.o
 
+obj-$(CONFIG_OLPC)             += olpc.o
+
 ###
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
@@ -101,4 +103,6 @@ ifeq ($(CONFIG_X86_64),y)
         obj-$(CONFIG_GART_IOMMU)       += pci-gart_64.o aperture_64.o
         obj-$(CONFIG_CALGARY_IOMMU)    += pci-calgary_64.o tce_64.o
         obj-$(CONFIG_SWIOTLB)          += pci-swiotlb_64.o
+
+        obj-$(CONFIG_PCI_MMCONFIG)     += mmconf-fam10h_64.o
 endif
index 977ed5cdeaa3b1b6a8d5f78b3446df7be7e21b53..c49ebcc6c41e84392fe1eeb1b473b01e881b1975 100644 (file)
@@ -771,6 +771,32 @@ static void __init acpi_register_lapic_address(unsigned long address)
                boot_cpu_physical_apicid  = GET_APIC_ID(read_apic_id());
 }
 
+static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
+{
+       int count;
+
+       if (!cpu_has_apic)
+               return -ENODEV;
+
+       /*
+        * Note that the LAPIC address is obtained from the MADT (32-bit value)
+        * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
+        */
+
+       count =
+           acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
+                                 acpi_parse_lapic_addr_ovr, 0);
+       if (count < 0) {
+               printk(KERN_ERR PREFIX
+                      "Error parsing LAPIC address override entry\n");
+               return count;
+       }
+
+       acpi_register_lapic_address(acpi_lapic_addr);
+
+       return count;
+}
+
 static int __init acpi_parse_madt_lapic_entries(void)
 {
        int count;
@@ -901,6 +927,33 @@ static inline int acpi_parse_madt_ioapic_entries(void)
 }
 #endif /* !CONFIG_X86_IO_APIC */
 
+static void __init early_acpi_process_madt(void)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+       int error;
+
+       if (!acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt)) {
+
+               /*
+                * Parse MADT LAPIC entries
+                */
+               error = early_acpi_parse_madt_lapic_addr_ovr();
+               if (!error) {
+                       acpi_lapic = 1;
+                       smp_found_config = 1;
+               }
+               if (error == -EINVAL) {
+                       /*
+                        * Dell Precision Workstation 410, 610 come here.
+                        */
+                       printk(KERN_ERR PREFIX
+                              "Invalid BIOS MADT, disabling ACPI\n");
+                       disable_acpi();
+               }
+       }
+#endif
+}
+
 static void __init acpi_process_madt(void)
 {
 #ifdef CONFIG_X86_LOCAL_APIC
@@ -1233,6 +1286,23 @@ int __init acpi_boot_table_init(void)
        return 0;
 }
 
+int __init early_acpi_boot_init(void)
+{
+       /*
+        * If acpi_disabled, bail out
+        * One exception: acpi=ht continues far enough to enumerate LAPICs
+        */
+       if (acpi_disabled && !acpi_ht)
+               return 1;
+
+       /*
+        * Process the Multiple APIC Description Table (MADT), if present
+        */
+       early_acpi_process_madt();
+
+       return 0;
+}
+
 int __init acpi_boot_init(void)
 {
        /*
index 670c3c311289b185cd3fc3a2f12c64bc31a3cc4c..92588083950f8106bd08aafb081ebe46ce3023fd 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/signal.h>
 #include <linux/personality.h>
 #include <linux/suspend.h>
+#include <linux/kbuild.h>
 #include <asm/ucontext.h>
 #include "sigframe.h"
 #include <asm/pgtable.h>
 #include <linux/lguest.h>
 #include "../../../drivers/lguest/lg.h"
 
-#define DEFINE(sym, val) \
-        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : : )
-
-#define OFFSET(sym, str, mem) \
-       DEFINE(sym, offsetof(struct str, mem));
-
 /* workaround for a warning with -Wmissing-prototypes */
 void foo(void);
 
index 494e1e096ee6df0c986aeb14dbc3f8b7a407bb50..f126c05d6170a17e8fdd880b5973324eb8ebb7d0 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/errno.h> 
 #include <linux/hardirq.h>
 #include <linux/suspend.h>
+#include <linux/kbuild.h>
 #include <asm/pda.h>
 #include <asm/processor.h>
 #include <asm/segment.h>
 #include <asm/ia32.h>
 #include <asm/bootparam.h>
 
-#define DEFINE(sym, val) \
-        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : : )
-
-#define OFFSET(sym, str, mem) \
-       DEFINE(sym, offsetof(struct str, mem))
-
 #define __NO_STUBS 1
 #undef __SYSCALL
 #undef _ASM_X86_64_UNISTD_H_
index 8db8f73503b3cf8a82e9c550da8535aa0cade0d1..b0c8208df9fa17363b5a3ed5ce35bdec8c52ad25 100644 (file)
@@ -601,6 +601,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
            policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
                policy->cpus = perf->shared_cpu_map;
        }
+       policy->related_cpus = perf->shared_cpu_map;
 
 #ifdef CONFIG_SMP
        dmi_check_system(sw_any_bug_dmi_table);
index 353efe4f5017aeaf8c75abcf97639dd8b07dc2d1..5d241ce94a44f4f5b0fceb7a7a8292e08b6d9b08 100644 (file)
@@ -90,7 +90,7 @@ u8 mtrr_type_lookup(u64 start, u64 end)
         * Look of multiple ranges matching this address and pick type
         * as per MTRR precedence
         */
-       if (!mtrr_state.enabled & 2) {
+       if (!(mtrr_state.enabled & 2)) {
                return mtrr_state.def_type;
        }
 
index 1960f1985e5e107c52fb2a5d5dd6a2aa89c64021..84c480bb3715af21405c6d55fab0f3160cbf3a59 100644 (file)
@@ -424,7 +424,7 @@ static int __init mtrr_if_init(void)
                return -ENODEV;
 
        proc_root_mtrr =
-               proc_create("mtrr", S_IWUSR | S_IRUGO, &proc_root, &mtrr_fops);
+               proc_create("mtrr", S_IWUSR | S_IRUGO, NULL, &mtrr_fops);
 
        if (proc_root_mtrr)
                proc_root_mtrr->owner = THIS_MODULE;
index 645ee5e32a27184c714355c8e916951ef3605711..124480c0008dd2a5e348cd2db7b928ff13d3aa41 100644 (file)
@@ -100,7 +100,7 @@ void __init free_early(unsigned long start, unsigned long end)
        for (j = i + 1; j < MAX_EARLY_RES && early_res[j].end; j++)
                ;
 
-       memcpy(&early_res[i], &early_res[i + 1],
+       memmove(&early_res[i], &early_res[i + 1],
               (j - 1 - i) * sizeof(struct early_res));
 
        early_res[j - 1].end = 0;
index 00bda7bcda63741178db3ad46b444fe25c8b87a7..147352df28b9c74146a102f6c8b22b17e2b11d6d 100644 (file)
@@ -190,8 +190,6 @@ void irq_ctx_exit(int cpu)
        hardirq_ctx[cpu] = NULL;
 }
 
-extern asmlinkage void __do_softirq(void);
-
 asmlinkage void do_softirq(void)
 {
        unsigned long flags;
diff --git a/arch/x86/kernel/mmconf-fam10h_64.c b/arch/x86/kernel/mmconf-fam10h_64.c
new file mode 100644 (file)
index 0000000..edc5fbf
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * AMD Family 10h mmconfig enablement
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/dmi.h>
+#include <asm/pci-direct.h>
+#include <linux/sort.h>
+#include <asm/io.h>
+#include <asm/msr.h>
+#include <asm/acpi.h>
+
+#include "../pci/pci.h"
+
+struct pci_hostbridge_probe {
+       u32 bus;
+       u32 slot;
+       u32 vendor;
+       u32 device;
+};
+
+static u64 __cpuinitdata fam10h_pci_mmconf_base;
+static int __cpuinitdata fam10h_pci_mmconf_base_status;
+
+static struct pci_hostbridge_probe pci_probes[] __cpuinitdata = {
+       { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1200 },
+       { 0xff, 0, PCI_VENDOR_ID_AMD, 0x1200 },
+};
+
+struct range {
+       u64 start;
+       u64 end;
+};
+
+static int __cpuinit cmp_range(const void *x1, const void *x2)
+{
+       const struct range *r1 = x1;
+       const struct range *r2 = x2;
+       int start1, start2;
+
+       start1 = r1->start >> 32;
+       start2 = r2->start >> 32;
+
+       return start1 - start2;
+}
+
+/*[47:0] */
+/* need to avoid (0xfd<<32) and (0xfe<<32), ht used space */
+#define FAM10H_PCI_MMCONF_BASE (0xfcULL<<32)
+#define BASE_VALID(b) ((b != (0xfdULL << 32)) && (b != (0xfeULL << 32)))
+static void __cpuinit get_fam10h_pci_mmconf_base(void)
+{
+       int i;
+       unsigned bus;
+       unsigned slot;
+       int found;
+
+       u64 val;
+       u32 address;
+       u64 tom2;
+       u64 base = FAM10H_PCI_MMCONF_BASE;
+
+       int hi_mmio_num;
+       struct range range[8];
+
+       /* only try to get setting from BSP */
+       /* -1 or 1 */
+       if (fam10h_pci_mmconf_base_status)
+               return;
+
+       if (!early_pci_allowed())
+               goto fail;
+
+       found = 0;
+       for (i = 0; i < ARRAY_SIZE(pci_probes); i++) {
+               u32 id;
+               u16 device;
+               u16 vendor;
+
+               bus = pci_probes[i].bus;
+               slot = pci_probes[i].slot;
+               id = read_pci_config(bus, slot, 0, PCI_VENDOR_ID);
+
+               vendor = id & 0xffff;
+               device = (id>>16) & 0xffff;
+               if (pci_probes[i].vendor == vendor &&
+                   pci_probes[i].device == device) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (!found)
+               goto fail;
+
+       /* SYS_CFG */
+       address = MSR_K8_SYSCFG;
+       rdmsrl(address, val);
+
+       /* TOP_MEM2 is not enabled? */
+       if (!(val & (1<<21))) {
+               tom2 = 0;
+       } else {
+               /* TOP_MEM2 */
+               address = MSR_K8_TOP_MEM2;
+               rdmsrl(address, val);
+               tom2 = val & (0xffffULL<<32);
+       }
+
+       if (base <= tom2)
+               base = tom2 + (1ULL<<32);
+
+       /*
+        * need to check if the range is in the high mmio range that is
+        * above 4G
+        */
+       hi_mmio_num = 0;
+       for (i = 0; i < 8; i++) {
+               u32 reg;
+               u64 start;
+               u64 end;
+               reg = read_pci_config(bus, slot, 1, 0x80 + (i << 3));
+               if (!(reg & 3))
+                       continue;
+
+               start = (((u64)reg) << 8) & (0xffULL << 32); /* 39:16 on 31:8*/
+               reg = read_pci_config(bus, slot, 1, 0x84 + (i << 3));
+               end = (((u64)reg) << 8) & (0xffULL << 32); /* 39:16 on 31:8*/
+
+               if (!end)
+                       continue;
+
+               range[hi_mmio_num].start = start;
+               range[hi_mmio_num].end = end;
+               hi_mmio_num++;
+       }
+
+       if (!hi_mmio_num)
+               goto out;
+
+       /* sort the range */
+       sort(range, hi_mmio_num, sizeof(struct range), cmp_range, NULL);
+
+       if (range[hi_mmio_num - 1].end < base)
+               goto out;
+       if (range[0].start > base)
+               goto out;
+
+       /* need to find one window */
+       base = range[0].start - (1ULL << 32);
+       if ((base > tom2) && BASE_VALID(base))
+               goto out;
+       base = range[hi_mmio_num - 1].end + (1ULL << 32);
+       if ((base > tom2) && BASE_VALID(base))
+               goto out;
+       /* need to find window between ranges */
+       if (hi_mmio_num > 1)
+       for (i = 0; i < hi_mmio_num - 1; i++) {
+               if (range[i + 1].start > (range[i].end + (1ULL << 32))) {
+                       base = range[i].end + (1ULL << 32);
+                       if ((base > tom2) && BASE_VALID(base))
+                               goto out;
+               }
+       }
+
+fail:
+       fam10h_pci_mmconf_base_status = -1;
+       return;
+out:
+       fam10h_pci_mmconf_base = base;
+       fam10h_pci_mmconf_base_status = 1;
+}
+
+void __cpuinit fam10h_check_enable_mmcfg(void)
+{
+       u64 val;
+       u32 address;
+
+       if (!(pci_probe & PCI_CHECK_ENABLE_AMD_MMCONF))
+               return;
+
+       address = MSR_FAM10H_MMIO_CONF_BASE;
+       rdmsrl(address, val);
+
+       /* try to make sure that AP's setting is identical to BSP setting */
+       if (val & FAM10H_MMIO_CONF_ENABLE) {
+               unsigned busnbits;
+               busnbits = (val >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) &
+                       FAM10H_MMIO_CONF_BUSRANGE_MASK;
+
+               /* only trust the one handle 256 buses, if acpi=off */
+               if (!acpi_pci_disabled || busnbits >= 8) {
+                       u64 base;
+                       base = val & (0xffffULL << 32);
+                       if (fam10h_pci_mmconf_base_status <= 0) {
+                               fam10h_pci_mmconf_base = base;
+                               fam10h_pci_mmconf_base_status = 1;
+                               return;
+                       } else if (fam10h_pci_mmconf_base ==  base)
+                               return;
+               }
+       }
+
+       /*
+        * if it is not enabled, try to enable it and assume only one segment
+        * with 256 buses
+        */
+       get_fam10h_pci_mmconf_base();
+       if (fam10h_pci_mmconf_base_status <= 0)
+               return;
+
+       printk(KERN_INFO "Enable MMCONFIG on AMD Family 10h\n");
+       val &= ~((FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT) |
+            (FAM10H_MMIO_CONF_BUSRANGE_MASK<<FAM10H_MMIO_CONF_BUSRANGE_SHIFT));
+       val |= fam10h_pci_mmconf_base | (8 << FAM10H_MMIO_CONF_BUSRANGE_SHIFT) |
+              FAM10H_MMIO_CONF_ENABLE;
+       wrmsrl(address, val);
+}
+
+static int __devinit set_check_enable_amd_mmconf(const struct dmi_system_id *d)
+{
+        pci_probe |= PCI_CHECK_ENABLE_AMD_MMCONF;
+        return 0;
+}
+
+static struct dmi_system_id __devinitdata mmconf_dmi_table[] = {
+        {
+                .callback = set_check_enable_amd_mmconf,
+                .ident = "Sun Microsystems Machine",
+                .matches = {
+                        DMI_MATCH(DMI_SYS_VENDOR, "Sun Microsystems"),
+                },
+        },
+       {}
+};
+
+void __init check_enable_amd_mmconf_dmi(void)
+{
+       dmi_check_system(mmconf_dmi_table);
+}
diff --git a/arch/x86/kernel/olpc.c b/arch/x86/kernel/olpc.c
new file mode 100644 (file)
index 0000000..3e66722
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * Support for the OLPC DCON and OLPC EC access
+ *
+ * Copyright Â© 2006  Advanced Micro Devices, Inc.
+ * Copyright Â© 2007-2008  Andres Salomon <dilinger@debian.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/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/string.h>
+#include <asm/geode.h>
+#include <asm/olpc.h>
+
+#ifdef CONFIG_OPEN_FIRMWARE
+#include <asm/ofw.h>
+#endif
+
+struct olpc_platform_t olpc_platform_info;
+EXPORT_SYMBOL_GPL(olpc_platform_info);
+
+static DEFINE_SPINLOCK(ec_lock);
+
+/* what the timeout *should* be (in ms) */
+#define EC_BASE_TIMEOUT 20
+
+/* the timeout that bugs in the EC might force us to actually use */
+static int ec_timeout = EC_BASE_TIMEOUT;
+
+static int __init olpc_ec_timeout_set(char *str)
+{
+       if (get_option(&str, &ec_timeout) != 1) {
+               ec_timeout = EC_BASE_TIMEOUT;
+               printk(KERN_ERR "olpc-ec:  invalid argument to "
+                               "'olpc_ec_timeout=', ignoring!\n");
+       }
+       printk(KERN_DEBUG "olpc-ec:  using %d ms delay for EC commands.\n",
+                       ec_timeout);
+       return 1;
+}
+__setup("olpc_ec_timeout=", olpc_ec_timeout_set);
+
+/*
+ * These {i,o}bf_status functions return whether the buffers are full or not.
+ */
+
+static inline unsigned int ibf_status(unsigned int port)
+{
+       return !!(inb(port) & 0x02);
+}
+
+static inline unsigned int obf_status(unsigned int port)
+{
+       return inb(port) & 0x01;
+}
+
+#define wait_on_ibf(p, d) __wait_on_ibf(__LINE__, (p), (d))
+static int __wait_on_ibf(unsigned int line, unsigned int port, int desired)
+{
+       unsigned int timeo;
+       int state = ibf_status(port);
+
+       for (timeo = ec_timeout; state != desired && timeo; timeo--) {
+               mdelay(1);
+               state = ibf_status(port);
+       }
+
+       if ((state == desired) && (ec_timeout > EC_BASE_TIMEOUT) &&
+                       timeo < (ec_timeout - EC_BASE_TIMEOUT)) {
+               printk(KERN_WARNING "olpc-ec:  %d: waited %u ms for IBF!\n",
+                               line, ec_timeout - timeo);
+       }
+
+       return !(state == desired);
+}
+
+#define wait_on_obf(p, d) __wait_on_obf(__LINE__, (p), (d))
+static int __wait_on_obf(unsigned int line, unsigned int port, int desired)
+{
+       unsigned int timeo;
+       int state = obf_status(port);
+
+       for (timeo = ec_timeout; state != desired && timeo; timeo--) {
+               mdelay(1);
+               state = obf_status(port);
+       }
+
+       if ((state == desired) && (ec_timeout > EC_BASE_TIMEOUT) &&
+                       timeo < (ec_timeout - EC_BASE_TIMEOUT)) {
+               printk(KERN_WARNING "olpc-ec:  %d: waited %u ms for OBF!\n",
+                               line, ec_timeout - timeo);
+       }
+
+       return !(state == desired);
+}
+
+/*
+ * This allows the kernel to run Embedded Controller commands.  The EC is
+ * documented at <http://wiki.laptop.org/go/Embedded_controller>, and the
+ * available EC commands are here:
+ * <http://wiki.laptop.org/go/Ec_specification>.  Unfortunately, while
+ * OpenFirmware's source is available, the EC's is not.
+ */
+int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,
+               unsigned char *outbuf,  size_t outlen)
+{
+       unsigned long flags;
+       int ret = -EIO;
+       int i;
+
+       spin_lock_irqsave(&ec_lock, flags);
+
+       /* Clear OBF */
+       for (i = 0; i < 10 && (obf_status(0x6c) == 1); i++)
+               inb(0x68);
+       if (i == 10) {
+               printk(KERN_ERR "olpc-ec:  timeout while attempting to "
+                               "clear OBF flag!\n");
+               goto err;
+       }
+
+       if (wait_on_ibf(0x6c, 0)) {
+               printk(KERN_ERR "olpc-ec:  timeout waiting for EC to "
+                               "quiesce!\n");
+               goto err;
+       }
+
+restart:
+       /*
+        * Note that if we time out during any IBF checks, that's a failure;
+        * we have to return.  There's no way for the kernel to clear that.
+        *
+        * If we time out during an OBF check, we can restart the command;
+        * reissuing it will clear the OBF flag, and we should be alright.
+        * The OBF flag will sometimes misbehave due to what we believe
+        * is a hardware quirk..
+        */
+       printk(KERN_DEBUG "olpc-ec:  running cmd 0x%x\n", cmd);
+       outb(cmd, 0x6c);
+
+       if (wait_on_ibf(0x6c, 0)) {
+               printk(KERN_ERR "olpc-ec:  timeout waiting for EC to read "
+                               "command!\n");
+               goto err;
+       }
+
+       if (inbuf && inlen) {
+               /* write data to EC */
+               for (i = 0; i < inlen; i++) {
+                       if (wait_on_ibf(0x6c, 0)) {
+                               printk(KERN_ERR "olpc-ec:  timeout waiting for"
+                                               " EC accept data!\n");
+                               goto err;
+                       }
+                       printk(KERN_DEBUG "olpc-ec:  sending cmd arg 0x%x\n",
+                                       inbuf[i]);
+                       outb(inbuf[i], 0x68);
+               }
+       }
+       if (outbuf && outlen) {
+               /* read data from EC */
+               for (i = 0; i < outlen; i++) {
+                       if (wait_on_obf(0x6c, 1)) {
+                               printk(KERN_ERR "olpc-ec:  timeout waiting for"
+                                               " EC to provide data!\n");
+                               goto restart;
+                       }
+                       outbuf[i] = inb(0x68);
+                       printk(KERN_DEBUG "olpc-ec:  received 0x%x\n",
+                                       outbuf[i]);
+               }
+       }
+
+       ret = 0;
+err:
+       spin_unlock_irqrestore(&ec_lock, flags);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(olpc_ec_cmd);
+
+#ifdef CONFIG_OPEN_FIRMWARE
+static void __init platform_detect(void)
+{
+       size_t propsize;
+       u32 rev;
+
+       if (ofw("getprop", 4, 1, NULL, "board-revision-int", &rev, 4,
+                       &propsize) || propsize != 4) {
+               printk(KERN_ERR "ofw: getprop call failed!\n");
+               rev = 0;
+       }
+       olpc_platform_info.boardrev = be32_to_cpu(rev);
+}
+#else
+static void __init platform_detect(void)
+{
+       /* stopgap until OFW support is added to the kernel */
+       olpc_platform_info.boardrev = be32_to_cpu(0xc2);
+}
+#endif
+
+static int __init olpc_init(void)
+{
+       unsigned char *romsig;
+
+       /* The ioremap check is dangerous; limit what we run it on */
+       if (!is_geode() || geode_has_vsa2())
+               return 0;
+
+       spin_lock_init(&ec_lock);
+
+       romsig = ioremap(0xffffffc0, 16);
+       if (!romsig)
+               return 0;
+
+       if (strncmp(romsig, "CL1   Q", 7))
+               goto unmap;
+       if (strncmp(romsig+6, romsig+13, 3)) {
+               printk(KERN_INFO "OLPC BIOS signature looks invalid.  "
+                               "Assuming not OLPC\n");
+               goto unmap;
+       }
+
+       printk(KERN_INFO "OLPC board with OpenFirmware %.16s\n", romsig);
+       olpc_platform_info.flags |= OLPC_F_PRESENT;
+
+       /* get the platform revision */
+       platform_detect();
+
+       /* assume B1 and above models always have a DCON */
+       if (olpc_board_at_least(olpc_board(0xb1)))
+               olpc_platform_info.flags |= OLPC_F_DCON;
+
+       /* get the EC revision */
+       olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0,
+                       (unsigned char *) &olpc_platform_info.ecver, 1);
+
+       /* check to see if the VSA exists */
+       if (geode_has_vsa2())
+               olpc_platform_info.flags |= OLPC_F_VSA;
+
+       printk(KERN_INFO "OLPC board revision %s%X (EC=%x)\n",
+                       ((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "",
+                       olpc_platform_info.boardrev >> 4,
+                       olpc_platform_info.ecver);
+
+unmap:
+       iounmap(romsig);
+       return 0;
+}
+
+postcore_initcall(olpc_init);
index a94fb959a87a3f35c0eec00bdf696b195b378d30..22c14e21c97c435a8d172d8f23159738bf0dbe2f 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/crash_dump.h>
 #include <linux/root_dev.h>
 #include <linux/pci.h>
+#include <asm/pci-direct.h>
 #include <linux/efi.h>
 #include <linux/acpi.h>
 #include <linux/kallsyms.h>
@@ -40,6 +41,7 @@
 #include <linux/dmi.h>
 #include <linux/dma-mapping.h>
 #include <linux/ctype.h>
+#include <linux/sort.h>
 #include <linux/uaccess.h>
 #include <linux/init_ohci1394_dma.h>
 #include <linux/kvm_para.h>
@@ -288,6 +290,18 @@ static void __init parse_setup_data(void)
        }
 }
 
+#ifdef CONFIG_PCI_MMCONFIG
+extern void __cpuinit fam10h_check_enable_mmcfg(void);
+extern void __init check_enable_amd_mmconf_dmi(void);
+#else
+void __cpuinit fam10h_check_enable_mmcfg(void)
+{
+}
+void __init check_enable_amd_mmconf_dmi(void)
+{
+}
+#endif
+
 /*
  * setup_arch - architecture-specific boot-time initializations
  *
@@ -515,6 +529,9 @@ void __init setup_arch(char **cmdline_p)
        conswitchp = &dummy_con;
 #endif
 #endif
+
+       /* do this before identify_cpu for boot cpu */
+       check_enable_amd_mmconf_dmi();
 }
 
 static int __cpuinit get_model_name(struct cpuinfo_x86 *c)
@@ -767,6 +784,9 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
        /* MFENCE stops RDTSC speculation */
        set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
 
+       if (c->x86 == 0x10)
+               fam10h_check_enable_mmcfg();
+
        if (amd_apic_timer_broken())
                disable_apic_timer = 1;
 
index 8e05e7f7bd40cc779887c71e91769a22e572f09e..d92373630963f980fb5471a0d96d903b5d4b18bf 100644 (file)
@@ -57,7 +57,7 @@ sys_sigsuspend(int history0, int history1, old_sigset_t mask)
 
        current->state = TASK_INTERRUPTIBLE;
        schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
+       set_restore_sigmask();
 
        return -ERESTARTNOHAND;
 }
@@ -593,7 +593,7 @@ static void do_signal(struct pt_regs *regs)
        if (!user_mode(regs))
                return;
 
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+       if (current_thread_info()->status & TS_RESTORE_SIGMASK)
                oldset = &current->saved_sigmask;
        else
                oldset = &current->blocked;
@@ -612,13 +612,12 @@ static void do_signal(struct pt_regs *regs)
                /* Whee! Actually deliver the signal.  */
                if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
                        /*
-                        * a signal was successfully delivered; the saved
+                        * A signal was successfully delivered; the saved
                         * sigmask will have been stored in the signal frame,
                         * and will be restored by sigreturn, so we can simply
-                        * clear the TIF_RESTORE_SIGMASK flag
+                        * clear the TS_RESTORE_SIGMASK flag.
                         */
-                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                               clear_thread_flag(TIF_RESTORE_SIGMASK);
+                       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
                }
                return;
        }
@@ -645,8 +644,8 @@ static void do_signal(struct pt_regs *regs)
         * If there's no signal to deliver, we just put the saved sigmask
         * back.
         */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
+       if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
+               current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
                sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
        }
 }
@@ -665,7 +664,7 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
        }
 
        /* deal with pending signal delivery */
-       if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+       if (thread_info_flags & _TIF_SIGPENDING)
                do_signal(regs);
 
        if (thread_info_flags & _TIF_HRTICK_RESCHED)
index ccb2a4560c2d91496bdbee9d35ed04d07c9f65bf..e53b267662e712681d99b4b5ae6014af9bf790c1 100644 (file)
@@ -427,7 +427,7 @@ static void do_signal(struct pt_regs *regs)
        if (!user_mode(regs))
                return;
 
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+       if (current_thread_info()->status & TS_RESTORE_SIGMASK)
                oldset = &current->saved_sigmask;
        else
                oldset = &current->blocked;
@@ -444,11 +444,13 @@ static void do_signal(struct pt_regs *regs)
 
                /* Whee!  Actually deliver the signal.  */
                if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
-                       /* a signal was successfully delivered; the saved
+                       /*
+                        * A signal was successfully delivered; the saved
                         * sigmask will have been stored in the signal frame,
                         * and will be restored by sigreturn, so we can simply
-                        * clear the TIF_RESTORE_SIGMASK flag */
-                       clear_thread_flag(TIF_RESTORE_SIGMASK);
+                        * clear the TS_RESTORE_SIGMASK flag.
+                        */
+                       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
                }
                return;
        }
@@ -476,8 +478,8 @@ static void do_signal(struct pt_regs *regs)
         * If there's no signal to deliver, we just put the saved sigmask
         * back.
         */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
+       if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
+               current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
                sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
        }
 }
@@ -498,7 +500,7 @@ void do_notify_resume(struct pt_regs *regs, void *unused,
 #endif /* CONFIG_X86_MCE */
 
        /* deal with pending signal delivery */
-       if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+       if (thread_info_flags & _TIF_SIGPENDING)
                do_signal(regs);
 
        if (thread_info_flags & _TIF_HRTICK_RESCHED)
index 04c662ba18f1dbf217326a9ffe2ade458617ee61..84241a256dc819bbb1f2fcaff679f189782f8564 100644 (file)
@@ -1149,14 +1149,10 @@ static int __init smp_sanity_check(unsigned max_cpus)
                                 "forcing use of dummy APIC emulation.\n");
                smpboot_clear_io_apic();
 #ifdef CONFIG_X86_32
-               if (nmi_watchdog == NMI_LOCAL_APIC) {
-                       printk(KERN_INFO "activating minimal APIC for"
-                                        "NMI watchdog use.\n");
-                       connect_bsp_APIC();
-                       setup_local_APIC();
-                       end_local_APIC_setup();
-               }
+               connect_bsp_APIC();
 #endif
+               setup_local_APIC();
+               end_local_APIC_setup();
                return -1;
        }
 
index 1a89e93f3f1ccfad3696921f25492e60f2bfdfbc..2ff21f398934b049975a427e463b046e9226d079 100644 (file)
@@ -115,7 +115,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-extern void (*late_time_init)(void);
 /* Duplicate of time_init() below, with hpet_enable part added */
 void __init hpet_time_init(void)
 {
index caf2a26f5cfd1b712c346a835b3755b842a466b7..ba8c0b75ab0ae8c4fbbaba61c4afd6637cf4bd4a 100644 (file)
@@ -133,7 +133,7 @@ int is_vsmp_box(void)
        }
 }
 #else
-static int __init detect_vsmp_box(void)
+static void __init detect_vsmp_box(void)
 {
 }
 int is_vsmp_box(void)
index 86808e666f9c2aeea15492a8609400915f819a09..1f476e477844df02d09f21ec23ddb8f5084c4cba 100644 (file)
 #include <linux/nodemask.h>
 #include <asm/io.h>
 #include <linux/pci_ids.h>
+#include <linux/acpi.h>
 #include <asm/types.h>
 #include <asm/mmzone.h>
 #include <asm/proto.h>
 #include <asm/e820.h>
 #include <asm/pci-direct.h>
 #include <asm/numa.h>
+#include <asm/mpspec.h>
+#include <asm/apic.h>
 
 static __init int find_northbridge(void)
 {
@@ -44,6 +47,30 @@ static __init int find_northbridge(void)
        return -1;
 }
 
+static __init void early_get_boot_cpu_id(void)
+{
+       /*
+        * need to get boot_cpu_id so can use that to create apicid_to_node
+        * in k8_scan_nodes()
+        */
+       /*
+        * Find possible boot-time SMP configuration:
+        */
+       early_find_smp_config();
+#ifdef CONFIG_ACPI
+       /*
+        * Read APIC information from ACPI tables.
+        */
+       early_acpi_boot_init();
+#endif
+       /*
+        * get boot-time SMP configuration:
+        */
+       if (smp_found_config)
+               early_get_smp_config();
+       early_init_lapic_mapping();
+}
+
 int __init k8_scan_nodes(unsigned long start, unsigned long end)
 {
        unsigned long prevbase;
@@ -56,6 +83,7 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
        unsigned cores;
        unsigned bits;
        int j;
+       unsigned apicid_base;
 
        if (!early_pci_allowed())
                return -1;
@@ -174,11 +202,19 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
        /* use the coreid bits from early_identify_cpu */
        bits = boot_cpu_data.x86_coreid_bits;
        cores = (1<<bits);
+       apicid_base = 0;
+       /* need to get boot_cpu_id early for system with apicid lifting */
+       early_get_boot_cpu_id();
+       if (boot_cpu_physical_apicid > 0) {
+               printk(KERN_INFO "BSP APIC ID: %02x\n",
+                                boot_cpu_physical_apicid);
+               apicid_base = boot_cpu_physical_apicid;
+       }
 
        for (i = 0; i < 8; i++) {
                if (nodes[i].start != nodes[i].end) {
                        nodeid = nodeids[i];
-                       for (j = 0; j < cores; j++)
+                       for (j = apicid_base; j < cores + apicid_base; j++)
                                apicid_to_node[(nodeid << bits) + j] = i;
                        setup_node_bootmem(i, nodes[i].start, nodes[i].end);
                }
index cdd6828b5abb4015f91091cf4ccc5d1a6432ded0..2a1516efb5426dcb79f6b77283e2aeb813811711 100644 (file)
@@ -3,6 +3,7 @@ obj-y                           := i386.o init.o
 obj-$(CONFIG_PCI_BIOS)         += pcbios.o
 obj-$(CONFIG_PCI_MMCONFIG)     += mmconfig_32.o direct.o mmconfig-shared.o
 obj-$(CONFIG_PCI_DIRECT)       += direct.o
+obj-$(CONFIG_PCI_OLPC)         += olpc.o
 
 pci-y                          := fixup.o
 pci-$(CONFIG_ACPI)             += acpi.o
@@ -10,5 +11,6 @@ pci-y                         += legacy.o irq.o
 
 pci-$(CONFIG_X86_VISWS)                := visws.o fixup.o
 pci-$(CONFIG_X86_NUMAQ)                := numa.o irq.o
+pci-$(CONFIG_NUMA)             += mp_bus_to_node.o
 
 obj-y                          += $(pci-y) common.o early.o
index 7d8c467bf14306cb42b03f9b32ee427b719d28f9..8fbd19832cf6795f34be5e61d0c9c9c942ee6b74 100644 (file)
@@ -13,5 +13,5 @@ obj-y                 += legacy.o irq.o common.o early.o
 # mmconfig has a 64bit special
 obj-$(CONFIG_PCI_MMCONFIG) += mmconfig_64.o direct.o mmconfig-shared.o
 
-obj-$(CONFIG_NUMA)     += k8-bus_64.o
+obj-y          += k8-bus_64.o
 
index 2664cb3fc96c51fe964f1750225983ecdd745e77..1a9c0c6a1a1847f88c0024b06d18dfbd91d8cc22 100644 (file)
@@ -191,7 +191,10 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
 {
        struct pci_bus *bus;
        struct pci_sysdata *sd;
+       int node;
+#ifdef CONFIG_ACPI_NUMA
        int pxm;
+#endif
 
        dmi_check_system(acpi_pciprobe_dmi_table);
 
@@ -201,6 +204,17 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
                return NULL;
        }
 
+       node = -1;
+#ifdef CONFIG_ACPI_NUMA
+       pxm = acpi_get_pxm(device->handle);
+       if (pxm >= 0)
+               node = pxm_to_node(pxm);
+       if (node != -1)
+               set_mp_bus_to_node(busnum, node);
+       else
+               node = get_mp_bus_to_node(busnum);
+#endif
+
        /* Allocate per-root-bus (not per bus) arch-specific data.
         * TODO: leak; this memory is never freed.
         * It's arguable whether it's worth the trouble to care.
@@ -212,13 +226,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
        }
 
        sd->domain = domain;
-       sd->node = -1;
-
-       pxm = acpi_get_pxm(device->handle);
-#ifdef CONFIG_ACPI_NUMA
-       if (pxm >= 0)
-               sd->node = pxm_to_node(pxm);
-#endif
+       sd->node = node;
        /*
         * Maybe the desired pci bus has been already scanned. In such case
         * it is unnecessary to scan the pci bus with the given domain,busnum.
@@ -238,9 +246,9 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
                kfree(sd);
 
 #ifdef CONFIG_ACPI_NUMA
-       if (bus != NULL) {
+       if (bus) {
                if (pxm >= 0) {
-                       printk("bus %d -> pxm %d -> node %d\n",
+                       printk(KERN_DEBUG "bus %02x -> pxm %d -> node %d\n",
                                busnum, pxm, pxm_to_node(pxm));
                }
        }
@@ -248,7 +256,6 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
 
        if (bus && (pci_probe & PCI_USE__CRS))
                get_current_resources(device, busnum, domain, bus);
-       
        return bus;
 }
 
index 75fcc29ecf52ac16d86429a8139ab23884cde4df..2a4d751818b731fd1ae0007ed2f1f9a94cdf12d1 100644 (file)
@@ -342,9 +342,14 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum)
                return NULL;
        }
 
+       sd->node = get_mp_bus_to_node(busnum);
+
        printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum);
+       bus = pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd);
+       if (!bus)
+               kfree(sd);
 
-       return pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd);
+       return bus;
 }
 
 extern u8 pci_cache_line_size;
@@ -420,6 +425,10 @@ char * __devinit  pcibios_setup(char *str)
                pci_probe &= ~PCI_PROBE_MMCONF;
                return NULL;
        }
+       else if (!strcmp(str, "check_enable_amd_mmconf")) {
+               pci_probe |= PCI_CHECK_ENABLE_AMD_MMCONF;
+               return NULL;
+       }
 #endif
        else if (!strcmp(str, "noacpi")) {
                acpi_noirq_set();
@@ -480,7 +489,7 @@ void pcibios_disable_device (struct pci_dev *dev)
                pcibios_disable_irq(dev);
 }
 
-struct pci_bus *__devinit pci_scan_bus_with_sysdata(int busno)
+struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops, int node)
 {
        struct pci_bus *bus = NULL;
        struct pci_sysdata *sd;
@@ -495,10 +504,15 @@ struct pci_bus *__devinit pci_scan_bus_with_sysdata(int busno)
                printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busno);
                return NULL;
        }
-       sd->node = -1;
-       bus = pci_scan_bus(busno, &pci_root_ops, sd);
+       sd->node = node;
+       bus = pci_scan_bus(busno, ops, sd);
        if (!bus)
                kfree(sd);
 
        return bus;
 }
+
+struct pci_bus *pci_scan_bus_with_sysdata(int busno)
+{
+       return pci_scan_bus_on_node(busno, &pci_root_ops, -1);
+}
index 42f3e4cad179754c1dfc2594e4f759695eca1089..21d1e0e0d535bfef58228d695b983c747dcea805 100644 (file)
@@ -258,7 +258,8 @@ void __init pci_direct_init(int type)
 {
        if (type == 0)
                return;
-       printk(KERN_INFO "PCI: Using configuration type %d\n", type);
+       printk(KERN_INFO "PCI: Using configuration type %d for base access\n",
+                type);
        if (type == 1)
                raw_pci_ops = &pci_direct_conf1;
        else
@@ -275,8 +276,10 @@ int __init pci_direct_probe(void)
        if (!region)
                goto type2;
 
-       if (pci_check_type1())
+       if (pci_check_type1()) {
+               raw_pci_ops = &pci_direct_conf1;
                return 1;
+       }
        release_resource(region);
 
  type2:
@@ -290,7 +293,6 @@ int __init pci_direct_probe(void)
                goto fail2;
 
        if (pci_check_type2()) {
-               printk(KERN_INFO "PCI: Using configuration type 2\n");
                raw_pci_ops = &pci_direct_conf2;
                return 2;
        }
index a5ef5f55137313fcb1faec0145200beac774d4f8..b60b2abd480cf774bad3f7c43e1e058c0a595681 100644 (file)
@@ -493,3 +493,20 @@ static void __devinit pci_siemens_interrupt_controller(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SIEMENS, 0x0015,
                          pci_siemens_interrupt_controller);
+
+/*
+ * Regular PCI devices have 256 bytes, but AMD Family 10h Opteron ext config
+ * have 4096 bytes.  Even if the device is capable, that doesn't mean we can
+ * access it.  Maybe we don't have a way to generate extended config space
+ * accesses.   So check it
+ */
+static void fam10h_pci_cfg_space_size(struct pci_dev *dev)
+{
+       dev->cfg_size = pci_cfg_space_size_ext(dev, 0);
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1200, fam10h_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1201, fam10h_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1202, fam10h_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1203, fam10h_pci_cfg_space_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1204, fam10h_pci_cfg_space_size);
index 3de9f9ba2da6aed8be73921f3f416ed8af444a49..dd30c6076b5d74ff1be2929d7b8f84081c6a8250 100644 (file)
@@ -6,16 +6,17 @@
    in the right sequence from here. */
 static __init int pci_access_init(void)
 {
-       int type __maybe_unused = 0;
-
 #ifdef CONFIG_PCI_DIRECT
+       int type = 0;
+
        type = pci_direct_probe();
 #endif
-#ifdef CONFIG_PCI_MMCONFIG
-       pci_mmcfg_init(type);
+
+       pci_mmcfg_early_init();
+
+#ifdef CONFIG_PCI_OLPC
+       pci_olpc_init();
 #endif
-       if (raw_pci_ops)
-               return 0;
 #ifdef CONFIG_PCI_BIOS
        pci_pcbios_init();
 #endif
@@ -28,7 +29,7 @@ static __init int pci_access_init(void)
 #ifdef CONFIG_PCI_DIRECT
        pci_direct_init(type);
 #endif
-       if (!raw_pci_ops)
+       if (!raw_pci_ops && !raw_pci_ext_ops)
                printk(KERN_ERR
                "PCI: Fatal: No config space access function found\n");
 
index 579745ca6b667dd0ccb7c62ac1133c42c7527088..0908fca901bf356ff2597ce13afbeffea35c641e 100644 (file)
@@ -136,9 +136,11 @@ static void __init pirq_peer_trick(void)
                busmap[e->bus] = 1;
        }
        for(i = 1; i < 256; i++) {
+               int node;
                if (!busmap[i] || pci_find_bus(0, i))
                        continue;
-               if (pci_scan_bus_with_sysdata(i))
+               node = get_mp_bus_to_node(i);
+               if (pci_scan_bus_on_node(i, &pci_root_ops, node))
                        printk(KERN_INFO "PCI: Discovered primary peer "
                               "bus %02x [IRQ]\n", i);
        }
index 9cc813e29706d3febdd70aacf5b4aa2d6e4940af..ab6d4b18a88fdcc01fc63835ca60f1eded7827e1 100644 (file)
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <asm/pci-direct.h>
 #include <asm/mpspec.h>
 #include <linux/cpumask.h>
+#include <linux/topology.h>
 
 /*
  * This discovers the pcibus <-> node mapping on AMD K8.
- *
- * RED-PEN need to call this again on PCI hotplug
- * RED-PEN empty cpus get reported wrong
+ * also get peer root bus resource for io,mmio
  */
 
-#define NODE_ID_REGISTER 0x60
-#define NODE_ID(dword) (dword & 0x07)
-#define LDT_BUS_NUMBER_REGISTER_0 0x94
-#define LDT_BUS_NUMBER_REGISTER_1 0xB4
-#define LDT_BUS_NUMBER_REGISTER_2 0xD4
-#define NR_LDT_BUS_NUMBER_REGISTERS 3
-#define SECONDARY_LDT_BUS_NUMBER(dword) ((dword >> 8) & 0xFF)
-#define SUBORDINATE_LDT_BUS_NUMBER(dword) ((dword >> 16) & 0xFF)
-#define PCI_DEVICE_ID_K8HTCONFIG 0x1100
+
+/*
+ * sub bus (transparent) will use entres from 3 to store extra from root,
+ * so need to make sure have enought slot there, increase PCI_BUS_NUM_RESOURCES?
+ */
+#define RES_NUM 16
+struct pci_root_info {
+       char name[12];
+       unsigned int res_num;
+       struct resource res[RES_NUM];
+       int bus_min;
+       int bus_max;
+       int node;
+       int link;
+};
+
+/* 4 at this time, it may become to 32 */
+#define PCI_ROOT_NR 4
+static int pci_root_num;
+static struct pci_root_info pci_root_info[PCI_ROOT_NR];
+
+#ifdef CONFIG_NUMA
+
+#define BUS_NR 256
+
+static int mp_bus_to_node[BUS_NR];
+
+void set_mp_bus_to_node(int busnum, int node)
+{
+       if (busnum >= 0 &&  busnum < BUS_NR)
+               mp_bus_to_node[busnum] = node;
+}
+
+int get_mp_bus_to_node(int busnum)
+{
+       int node = -1;
+
+       if (busnum < 0 || busnum > (BUS_NR - 1))
+               return node;
+
+       node = mp_bus_to_node[busnum];
+
+       /*
+        * let numa_node_id to decide it later in dma_alloc_pages
+        * if there is no ram on that node
+        */
+       if (node != -1 && !node_online(node))
+               node = -1;
+
+       return node;
+}
+#endif
+
+void set_pci_bus_resources_arch_default(struct pci_bus *b)
+{
+       int i;
+       int j;
+       struct pci_root_info *info;
+
+       /* if only one root bus, don't need to anything */
+       if (pci_root_num < 2)
+               return;
+
+       for (i = 0; i < pci_root_num; i++) {
+               if (pci_root_info[i].bus_min == b->number)
+                       break;
+       }
+
+       if (i == pci_root_num)
+               return;
+
+       info = &pci_root_info[i];
+       for (j = 0; j < info->res_num; j++) {
+               struct resource *res;
+               struct resource *root;
+
+               res = &info->res[j];
+               b->resource[j] = res;
+               if (res->flags & IORESOURCE_IO)
+                       root = &ioport_resource;
+               else
+                       root = &iomem_resource;
+               insert_resource(root, res);
+       }
+}
+
+#define RANGE_NUM 16
+
+struct res_range {
+       size_t start;
+       size_t end;
+};
+
+static void __init update_range(struct res_range *range, size_t start,
+                               size_t end)
+{
+       int i;
+       int j;
+
+       for (j = 0; j < RANGE_NUM; j++) {
+               if (!range[j].end)
+                       continue;
+
+               if (start <= range[j].start && end >= range[j].end) {
+                       range[j].start = 0;
+                       range[j].end = 0;
+                       continue;
+               }
+
+               if (start <= range[j].start && end < range[j].end && range[j].start < end + 1) {
+                       range[j].start = end + 1;
+                       continue;
+               }
+
+
+               if (start > range[j].start && end >= range[j].end && range[j].end > start - 1) {
+                       range[j].end = start - 1;
+                       continue;
+               }
+
+               if (start > range[j].start && end < range[j].end) {
+                       /* find the new spare */
+                       for (i = 0; i < RANGE_NUM; i++) {
+                               if (range[i].end == 0)
+                                       break;
+                       }
+                       if (i < RANGE_NUM) {
+                               range[i].end = range[j].end;
+                               range[i].start = end + 1;
+                       } else {
+                               printk(KERN_ERR "run of slot in ranges\n");
+                       }
+                       range[j].end = start - 1;
+                       continue;
+               }
+       }
+}
+
+static void __init update_res(struct pci_root_info *info, size_t start,
+                             size_t end, unsigned long flags, int merge)
+{
+       int i;
+       struct resource *res;
+
+       if (!merge)
+               goto addit;
+
+       /* try to merge it with old one */
+       for (i = 0; i < info->res_num; i++) {
+               size_t final_start, final_end;
+               size_t common_start, common_end;
+
+               res = &info->res[i];
+               if (res->flags != flags)
+                       continue;
+
+               common_start = max((size_t)res->start, start);
+               common_end = min((size_t)res->end, end);
+               if (common_start > common_end + 1)
+                       continue;
+
+               final_start = min((size_t)res->start, start);
+               final_end = max((size_t)res->end, end);
+
+               res->start = final_start;
+               res->end = final_end;
+               return;
+       }
+
+addit:
+
+       /* need to add that */
+       if (info->res_num >= RES_NUM)
+               return;
+
+       res = &info->res[info->res_num];
+       res->name = info->name;
+       res->flags = flags;
+       res->start = start;
+       res->end = end;
+       res->child = NULL;
+       info->res_num++;
+}
+
+struct pci_hostbridge_probe {
+       u32 bus;
+       u32 slot;
+       u32 vendor;
+       u32 device;
+};
+
+static struct pci_hostbridge_probe pci_probes[] __initdata = {
+       { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1100 },
+       { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1200 },
+       { 0xff, 0, PCI_VENDOR_ID_AMD, 0x1200 },
+       { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1300 },
+};
+
+static u64 __initdata fam10h_mmconf_start;
+static u64 __initdata fam10h_mmconf_end;
+static void __init get_pci_mmcfg_amd_fam10h_range(void)
+{
+       u32 address;
+       u64 base, msr;
+       unsigned segn_busn_bits;
+
+       /* assume all cpus from fam10h have mmconf */
+        if (boot_cpu_data.x86 < 0x10)
+               return;
+
+       address = MSR_FAM10H_MMIO_CONF_BASE;
+       rdmsrl(address, msr);
+
+       /* mmconfig is not enable */
+       if (!(msr & FAM10H_MMIO_CONF_ENABLE))
+               return;
+
+       base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT);
+
+       segn_busn_bits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) &
+                        FAM10H_MMIO_CONF_BUSRANGE_MASK;
+
+       fam10h_mmconf_start = base;
+       fam10h_mmconf_end = base + (1ULL<<(segn_busn_bits + 20)) - 1;
+}
 
 /**
- * fill_mp_bus_to_cpumask()
+ * early_fill_mp_bus_to_node()
+ * called before pcibios_scan_root and pci_scan_bus
  * fills the mp_bus_to_cpumask array based according to the LDT Bus Number
  * Registers found in the K8 northbridge
  */
-__init static int
-fill_mp_bus_to_cpumask(void)
+static int __init early_fill_mp_bus_info(void)
 {
-       struct pci_dev *nb_dev = NULL;
-       int i, j;
-       u32 ldtbus, nid;
-       static int lbnr[3] = {
-               LDT_BUS_NUMBER_REGISTER_0,
-               LDT_BUS_NUMBER_REGISTER_1,
-               LDT_BUS_NUMBER_REGISTER_2
-       };
-
-       while ((nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
-                       PCI_DEVICE_ID_K8HTCONFIG, nb_dev))) {
-               pci_read_config_dword(nb_dev, NODE_ID_REGISTER, &nid);
-
-               for (i = 0; i < NR_LDT_BUS_NUMBER_REGISTERS; i++) {
-                       pci_read_config_dword(nb_dev, lbnr[i], &ldtbus);
-                       /*
-                        * if there are no busses hanging off of the current
-                        * ldt link then both the secondary and subordinate
-                        * bus number fields are set to 0.
-                        * 
-                        * RED-PEN
-                        * This is slightly broken because it assumes
-                        * HT node IDs == Linux node ids, which is not always
-                        * true. However it is probably mostly true.
-                        */
-                       if (!(SECONDARY_LDT_BUS_NUMBER(ldtbus) == 0
-                               && SUBORDINATE_LDT_BUS_NUMBER(ldtbus) == 0)) {
-                               for (j = SECONDARY_LDT_BUS_NUMBER(ldtbus);
-                                    j <= SUBORDINATE_LDT_BUS_NUMBER(ldtbus);
-                                    j++) { 
-                                       struct pci_bus *bus;
-                                       struct pci_sysdata *sd;
-
-                                       long node = NODE_ID(nid);
-                                       /* Algorithm a bit dumb, but
-                                          it shouldn't matter here */
-                                       bus = pci_find_bus(0, j);
-                                       if (!bus)
-                                               continue;
-                                       if (!node_online(node))
-                                               node = 0;
-
-                                       sd = bus->sysdata;
-                                       sd->node = node;
-                               }               
+       int i;
+       int j;
+       unsigned bus;
+       unsigned slot;
+       int found;
+       int node;
+       int link;
+       int def_node;
+       int def_link;
+       struct pci_root_info *info;
+       u32 reg;
+       struct resource *res;
+       size_t start;
+       size_t end;
+       struct res_range range[RANGE_NUM];
+       u64 val;
+       u32 address;
+
+#ifdef CONFIG_NUMA
+       for (i = 0; i < BUS_NR; i++)
+               mp_bus_to_node[i] = -1;
+#endif
+
+       if (!early_pci_allowed())
+               return -1;
+
+       found = 0;
+       for (i = 0; i < ARRAY_SIZE(pci_probes); i++) {
+               u32 id;
+               u16 device;
+               u16 vendor;
+
+               bus = pci_probes[i].bus;
+               slot = pci_probes[i].slot;
+               id = read_pci_config(bus, slot, 0, PCI_VENDOR_ID);
+
+               vendor = id & 0xffff;
+               device = (id>>16) & 0xffff;
+               if (pci_probes[i].vendor == vendor &&
+                   pci_probes[i].device == device) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (!found)
+               return 0;
+
+       pci_root_num = 0;
+       for (i = 0; i < 4; i++) {
+               int min_bus;
+               int max_bus;
+               reg = read_pci_config(bus, slot, 1, 0xe0 + (i << 2));
+
+               /* Check if that register is enabled for bus range */
+               if ((reg & 7) != 3)
+                       continue;
+
+               min_bus = (reg >> 16) & 0xff;
+               max_bus = (reg >> 24) & 0xff;
+               node = (reg >> 4) & 0x07;
+#ifdef CONFIG_NUMA
+               for (j = min_bus; j <= max_bus; j++)
+                       mp_bus_to_node[j] = (unsigned char) node;
+#endif
+               link = (reg >> 8) & 0x03;
+
+               info = &pci_root_info[pci_root_num];
+               info->bus_min = min_bus;
+               info->bus_max = max_bus;
+               info->node = node;
+               info->link = link;
+               sprintf(info->name, "PCI Bus #%02x", min_bus);
+               pci_root_num++;
+       }
+
+       /* get the default node and link for left over res */
+       reg = read_pci_config(bus, slot, 0, 0x60);
+       def_node = (reg >> 8) & 0x07;
+       reg = read_pci_config(bus, slot, 0, 0x64);
+       def_link = (reg >> 8) & 0x03;
+
+       memset(range, 0, sizeof(range));
+       range[0].end = 0xffff;
+       /* io port resource */
+       for (i = 0; i < 4; i++) {
+               reg = read_pci_config(bus, slot, 1, 0xc0 + (i << 3));
+               if (!(reg & 3))
+                       continue;
+
+               start = reg & 0xfff000;
+               reg = read_pci_config(bus, slot, 1, 0xc4 + (i << 3));
+               node = reg & 0x07;
+               link = (reg >> 4) & 0x03;
+               end = (reg & 0xfff000) | 0xfff;
+
+               /* find the position */
+               for (j = 0; j < pci_root_num; j++) {
+                       info = &pci_root_info[j];
+                       if (info->node == node && info->link == link)
+                               break;
+               }
+               if (j == pci_root_num)
+                       continue; /* not found */
+
+               info = &pci_root_info[j];
+               printk(KERN_DEBUG "node %d link %d: io port [%llx, %llx]\n",
+                      node, link, (u64)start, (u64)end);
+
+               /* kernel only handle 16 bit only */
+               if (end > 0xffff)
+                       end = 0xffff;
+               update_res(info, start, end, IORESOURCE_IO, 1);
+               update_range(range, start, end);
+       }
+       /* add left over io port range to def node/link, [0, 0xffff] */
+       /* find the position */
+       for (j = 0; j < pci_root_num; j++) {
+               info = &pci_root_info[j];
+               if (info->node == def_node && info->link == def_link)
+                       break;
+       }
+       if (j < pci_root_num) {
+               info = &pci_root_info[j];
+               for (i = 0; i < RANGE_NUM; i++) {
+                       if (!range[i].end)
+                               continue;
+
+                       update_res(info, range[i].start, range[i].end,
+                                  IORESOURCE_IO, 1);
+               }
+       }
+
+       memset(range, 0, sizeof(range));
+       /* 0xfd00000000-0xffffffffff for HT */
+       range[0].end = (0xfdULL<<32) - 1;
+
+       /* need to take out [0, TOM) for RAM*/
+       address = MSR_K8_TOP_MEM1;
+       rdmsrl(address, val);
+       end = (val & 0xffffff8000000ULL);
+       printk(KERN_INFO "TOM: %016lx aka %ldM\n", end, end>>20);
+       if (end < (1ULL<<32))
+               update_range(range, 0, end - 1);
+
+       /* get mmconfig */
+       get_pci_mmcfg_amd_fam10h_range();
+       /* need to take out mmconf range */
+       if (fam10h_mmconf_end) {
+               printk(KERN_DEBUG "Fam 10h mmconf [%llx, %llx]\n", fam10h_mmconf_start, fam10h_mmconf_end);
+               update_range(range, fam10h_mmconf_start, fam10h_mmconf_end);
+       }
+
+       /* mmio resource */
+       for (i = 0; i < 8; i++) {
+               reg = read_pci_config(bus, slot, 1, 0x80 + (i << 3));
+               if (!(reg & 3))
+                       continue;
+
+               start = reg & 0xffffff00; /* 39:16 on 31:8*/
+               start <<= 8;
+               reg = read_pci_config(bus, slot, 1, 0x84 + (i << 3));
+               node = reg & 0x07;
+               link = (reg >> 4) & 0x03;
+               end = (reg & 0xffffff00);
+               end <<= 8;
+               end |= 0xffff;
+
+               /* find the position */
+               for (j = 0; j < pci_root_num; j++) {
+                       info = &pci_root_info[j];
+                       if (info->node == node && info->link == link)
+                               break;
+               }
+               if (j == pci_root_num)
+                       continue; /* not found */
+
+               info = &pci_root_info[j];
+
+               printk(KERN_DEBUG "node %d link %d: mmio [%llx, %llx]",
+                      node, link, (u64)start, (u64)end);
+               /*
+                * some sick allocation would have range overlap with fam10h
+                * mmconf range, so need to update start and end.
+                */
+               if (fam10h_mmconf_end) {
+                       int changed = 0;
+                       u64 endx = 0;
+                       if (start >= fam10h_mmconf_start &&
+                           start <= fam10h_mmconf_end) {
+                               start = fam10h_mmconf_end + 1;
+                               changed = 1;
+                       }
+
+                       if (end >= fam10h_mmconf_start &&
+                           end <= fam10h_mmconf_end) {
+                               end = fam10h_mmconf_start - 1;
+                               changed = 1;
+                       }
+
+                       if (start < fam10h_mmconf_start &&
+                           end > fam10h_mmconf_end) {
+                               /* we got a hole */
+                               endx = fam10h_mmconf_start - 1;
+                               update_res(info, start, endx, IORESOURCE_MEM, 0);
+                               update_range(range, start, endx);
+                               printk(KERN_CONT " ==> [%llx, %llx]", (u64)start, endx);
+                               start = fam10h_mmconf_end + 1;
+                               changed = 1;
+                       }
+                       if (changed) {
+                               if (start <= end) {
+                                       printk(KERN_CONT " %s [%llx, %llx]", endx?"and":"==>", (u64)start, (u64)end);
+                               } else {
+                                       printk(KERN_CONT "%s\n", endx?"":" ==> none");
+                                       continue;
+                               }
                        }
                }
+
+               update_res(info, start, end, IORESOURCE_MEM, 1);
+               update_range(range, start, end);
+               printk(KERN_CONT "\n");
+       }
+
+       /* need to take out [4G, TOM2) for RAM*/
+       /* SYS_CFG */
+       address = MSR_K8_SYSCFG;
+       rdmsrl(address, val);
+       /* TOP_MEM2 is enabled? */
+       if (val & (1<<21)) {
+               /* TOP_MEM2 */
+               address = MSR_K8_TOP_MEM2;
+               rdmsrl(address, val);
+               end = (val & 0xffffff8000000ULL);
+               printk(KERN_INFO "TOM2: %016lx aka %ldM\n", end, end>>20);
+               update_range(range, 1ULL<<32, end - 1);
+       }
+
+       /*
+        * add left over mmio range to def node/link ?
+        * that is tricky, just record range in from start_min to 4G
+        */
+       for (j = 0; j < pci_root_num; j++) {
+               info = &pci_root_info[j];
+               if (info->node == def_node && info->link == def_link)
+                       break;
+       }
+       if (j < pci_root_num) {
+               info = &pci_root_info[j];
+
+               for (i = 0; i < RANGE_NUM; i++) {
+                       if (!range[i].end)
+                               continue;
+
+                       update_res(info, range[i].start, range[i].end,
+                                  IORESOURCE_MEM, 1);
+               }
+       }
+
+#ifdef CONFIG_NUMA
+       for (i = 0; i < BUS_NR; i++) {
+               node = mp_bus_to_node[i];
+               if (node >= 0)
+                       printk(KERN_DEBUG "bus: %02x to node: %02x\n", i, node);
+       }
+#endif
+
+       for (i = 0; i < pci_root_num; i++) {
+               int res_num;
+               int busnum;
+
+               info = &pci_root_info[i];
+               res_num = info->res_num;
+               busnum = info->bus_min;
+               printk(KERN_DEBUG "bus: [%02x,%02x] on node %x link %x\n",
+                      info->bus_min, info->bus_max, info->node, info->link);
+               for (j = 0; j < res_num; j++) {
+                       res = &info->res[j];
+                       printk(KERN_DEBUG "bus: %02x index %x %s: [%llx, %llx]\n",
+                              busnum, j,
+                              (res->flags & IORESOURCE_IO)?"io port":"mmio",
+                              res->start, res->end);
+               }
        }
 
        return 0;
 }
 
-fs_initcall(fill_mp_bus_to_cpumask);
+postcore_initcall(early_fill_mp_bus_info);
index e041ced0ce138714a93147f9cc5015e0f7f51d3e..a67921ce60af1faabf9c8ccbf538b546103ebb04 100644 (file)
@@ -12,6 +12,7 @@
 static void __devinit pcibios_fixup_peer_bridges(void)
 {
        int n, devfn;
+       long node;
 
        if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff)
                return;
@@ -21,12 +22,13 @@ static void __devinit pcibios_fixup_peer_bridges(void)
                u32 l;
                if (pci_find_bus(0, n))
                        continue;
+               node = get_mp_bus_to_node(n);
                for (devfn = 0; devfn < 256; devfn += 8) {
                        if (!raw_pci_read(0, n, devfn, PCI_VENDOR_ID, 2, &l) &&
                            l != 0x0000 && l != 0xffff) {
                                DBG("Found device at %02x:%02x [%04x]\n", n, devfn, l);
                                printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
-                               pci_scan_bus_with_sysdata(n);
+                               pci_scan_bus_on_node(n, &pci_root_ops, node);
                                break;
                        }
                }
index 8d54df4dfaad551518bcbf77cbe0be20d0f36562..0cfebecf2a8f128cc2b52f632a95d55eef397fb3 100644 (file)
@@ -28,7 +28,7 @@ static int __initdata pci_mmcfg_resources_inserted;
 static const char __init *pci_mmcfg_e7520(void)
 {
        u32 win;
-       pci_direct_conf1.read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win);
+       raw_pci_ops->read(0, 0, PCI_DEVFN(0, 0), 0xce, 2, &win);
 
        win = win & 0xf000;
        if(win == 0x0000 || win == 0xf000)
@@ -53,7 +53,7 @@ static const char __init *pci_mmcfg_intel_945(void)
 
        pci_mmcfg_config_num = 1;
 
-       pci_direct_conf1.read(0, 0, PCI_DEVFN(0,0), 0x48, 4, &pciexbar);
+       raw_pci_ops->read(0, 0, PCI_DEVFN(0, 0), 0x48, 4, &pciexbar);
 
        /* Enable bit */
        if (!(pciexbar & 1))
@@ -100,33 +100,102 @@ static const char __init *pci_mmcfg_intel_945(void)
        return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
 }
 
+static const char __init *pci_mmcfg_amd_fam10h(void)
+{
+       u32 low, high, address;
+       u64 base, msr;
+       int i;
+       unsigned segnbits = 0, busnbits;
+
+       if (!(pci_probe & PCI_CHECK_ENABLE_AMD_MMCONF))
+               return NULL;
+
+       address = MSR_FAM10H_MMIO_CONF_BASE;
+       if (rdmsr_safe(address, &low, &high))
+               return NULL;
+
+       msr = high;
+       msr <<= 32;
+       msr |= low;
+
+       /* mmconfig is not enable */
+       if (!(msr & FAM10H_MMIO_CONF_ENABLE))
+               return NULL;
+
+       base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT);
+
+       busnbits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) &
+                        FAM10H_MMIO_CONF_BUSRANGE_MASK;
+
+       /*
+        * only handle bus 0 ?
+        * need to skip it
+        */
+       if (!busnbits)
+               return NULL;
+
+       if (busnbits > 8) {
+               segnbits = busnbits - 8;
+               busnbits = 8;
+       }
+
+       pci_mmcfg_config_num = (1 << segnbits);
+       pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]) *
+                                  pci_mmcfg_config_num, GFP_KERNEL);
+       if (!pci_mmcfg_config)
+               return NULL;
+
+       for (i = 0; i < (1 << segnbits); i++) {
+               pci_mmcfg_config[i].address = base + (1<<28) * i;
+               pci_mmcfg_config[i].pci_segment = i;
+               pci_mmcfg_config[i].start_bus_number = 0;
+               pci_mmcfg_config[i].end_bus_number = (1 << busnbits) - 1;
+       }
+
+       return "AMD Family 10h NB";
+}
+
 struct pci_mmcfg_hostbridge_probe {
+       u32 bus;
+       u32 devfn;
        u32 vendor;
        u32 device;
        const char *(*probe)(void);
 };
 
 static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = {
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
+       { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL,
+         PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
+       { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL,
+         PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
+       { 0, PCI_DEVFN(0x18, 0), PCI_VENDOR_ID_AMD,
+         0x1200, pci_mmcfg_amd_fam10h },
+       { 0xff, PCI_DEVFN(0, 0), PCI_VENDOR_ID_AMD,
+         0x1200, pci_mmcfg_amd_fam10h },
 };
 
 static int __init pci_mmcfg_check_hostbridge(void)
 {
        u32 l;
+       u32 bus, devfn;
        u16 vendor, device;
        int i;
        const char *name;
 
-       pci_direct_conf1.read(0, 0, PCI_DEVFN(0,0), 0, 4, &l);
-       vendor = l & 0xffff;
-       device = (l >> 16) & 0xffff;
+       if (!raw_pci_ops)
+               return 0;
 
        pci_mmcfg_config_num = 0;
        pci_mmcfg_config = NULL;
        name = NULL;
 
        for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) {
+               bus =  pci_mmcfg_probes[i].bus;
+               devfn = pci_mmcfg_probes[i].devfn;
+               raw_pci_ops->read(0, bus, devfn, 0, 4, &l);
+               vendor = l & 0xffff;
+               device = (l >> 16) & 0xffff;
+
                if (pci_mmcfg_probes[i].vendor == vendor &&
                    pci_mmcfg_probes[i].device == device)
                        name = pci_mmcfg_probes[i].probe();
@@ -173,9 +242,78 @@ static void __init pci_mmcfg_insert_resources(unsigned long resource_flags)
        pci_mmcfg_resources_inserted = 1;
 }
 
-static void __init pci_mmcfg_reject_broken(int type)
+static acpi_status __init check_mcfg_resource(struct acpi_resource *res,
+                                             void *data)
+{
+       struct resource *mcfg_res = data;
+       struct acpi_resource_address64 address;
+       acpi_status status;
+
+       if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) {
+               struct acpi_resource_fixed_memory32 *fixmem32 =
+                       &res->data.fixed_memory32;
+               if (!fixmem32)
+                       return AE_OK;
+               if ((mcfg_res->start >= fixmem32->address) &&
+                   (mcfg_res->end < (fixmem32->address +
+                                     fixmem32->address_length))) {
+                       mcfg_res->flags = 1;
+                       return AE_CTRL_TERMINATE;
+               }
+       }
+       if ((res->type != ACPI_RESOURCE_TYPE_ADDRESS32) &&
+           (res->type != ACPI_RESOURCE_TYPE_ADDRESS64))
+               return AE_OK;
+
+       status = acpi_resource_to_address64(res, &address);
+       if (ACPI_FAILURE(status) ||
+          (address.address_length <= 0) ||
+          (address.resource_type != ACPI_MEMORY_RANGE))
+               return AE_OK;
+
+       if ((mcfg_res->start >= address.minimum) &&
+           (mcfg_res->end < (address.minimum + address.address_length))) {
+               mcfg_res->flags = 1;
+               return AE_CTRL_TERMINATE;
+       }
+       return AE_OK;
+}
+
+static acpi_status __init find_mboard_resource(acpi_handle handle, u32 lvl,
+               void *context, void **rv)
+{
+       struct resource *mcfg_res = context;
+
+       acpi_walk_resources(handle, METHOD_NAME__CRS,
+                           check_mcfg_resource, context);
+
+       if (mcfg_res->flags)
+               return AE_CTRL_TERMINATE;
+
+       return AE_OK;
+}
+
+static int __init is_acpi_reserved(unsigned long start, unsigned long end)
+{
+       struct resource mcfg_res;
+
+       mcfg_res.start = start;
+       mcfg_res.end = end;
+       mcfg_res.flags = 0;
+
+       acpi_get_devices("PNP0C01", find_mboard_resource, &mcfg_res, NULL);
+
+       if (!mcfg_res.flags)
+               acpi_get_devices("PNP0C02", find_mboard_resource, &mcfg_res,
+                                NULL);
+
+       return mcfg_res.flags;
+}
+
+static void __init pci_mmcfg_reject_broken(int early)
 {
        typeof(pci_mmcfg_config[0]) *cfg;
+       int i;
 
        if ((pci_mmcfg_config_num == 0) ||
            (pci_mmcfg_config == NULL) ||
@@ -184,51 +322,80 @@ static void __init pci_mmcfg_reject_broken(int type)
 
        cfg = &pci_mmcfg_config[0];
 
-       /*
-        * Handle more broken MCFG tables on Asus etc.
-        * They only contain a single entry for bus 0-0.
-        */
-       if (pci_mmcfg_config_num == 1 &&
-           cfg->pci_segment == 0 &&
-           (cfg->start_bus_number | cfg->end_bus_number) == 0) {
-               printk(KERN_ERR "PCI: start and end of bus number is 0. "
-                      "Rejected as broken MCFG.\n");
-               goto reject;
+       for (i = 0; i < pci_mmcfg_config_num; i++) {
+               int valid = 0;
+               u32 size = (cfg->end_bus_number + 1) << 20;
+               cfg = &pci_mmcfg_config[i];
+               printk(KERN_NOTICE "PCI: MCFG configuration %d: base %lx "
+                      "segment %hu buses %u - %u\n",
+                      i, (unsigned long)cfg->address, cfg->pci_segment,
+                      (unsigned int)cfg->start_bus_number,
+                      (unsigned int)cfg->end_bus_number);
+
+               if (!early &&
+                   is_acpi_reserved(cfg->address, cfg->address + size - 1)) {
+                       printk(KERN_NOTICE "PCI: MCFG area at %Lx reserved "
+                              "in ACPI motherboard resources\n",
+                              cfg->address);
+                       valid = 1;
+               }
+
+               if (valid)
+                       continue;
+
+               if (!early)
+                       printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not"
+                              " reserved in ACPI motherboard resources\n",
+                              cfg->address);
+               /* Don't try to do this check unless configuration
+                  type 1 is available. how about type 2 ?*/
+               if (raw_pci_ops && e820_all_mapped(cfg->address,
+                                                 cfg->address + size - 1,
+                                                 E820_RESERVED)) {
+                       printk(KERN_NOTICE
+                              "PCI: MCFG area at %Lx reserved in E820\n",
+                              cfg->address);
+                       valid = 1;
+               }
+
+               if (!valid)
+                       goto reject;
        }
 
-       /*
-        * Only do this check when type 1 works. If it doesn't work
-        * assume we run on a Mac and always use MCFG
-        */
-       if (type == 1 && !e820_all_mapped(cfg->address,
-                                         cfg->address + MMCONFIG_APER_MIN,
-                                         E820_RESERVED)) {
-               printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not"
-                      " E820-reserved\n", cfg->address);
-               goto reject;
-       }
        return;
 
 reject:
        printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
+       pci_mmcfg_arch_free();
        kfree(pci_mmcfg_config);
        pci_mmcfg_config = NULL;
        pci_mmcfg_config_num = 0;
 }
 
-void __init pci_mmcfg_init(int type)
-{
-       int known_bridge = 0;
+static int __initdata known_bridge;
 
+void __init __pci_mmcfg_init(int early)
+{
+       /* MMCONFIG disabled */
        if ((pci_probe & PCI_PROBE_MMCONF) == 0)
                return;
 
-       if (type == 1 && pci_mmcfg_check_hostbridge())
-               known_bridge = 1;
+       /* MMCONFIG already enabled */
+       if (!early && !(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF))
+               return;
+
+       /* for late to exit */
+       if (known_bridge)
+               return;
+
+       if (early) {
+               if (pci_mmcfg_check_hostbridge())
+                       known_bridge = 1;
+       }
 
        if (!known_bridge) {
                acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
-               pci_mmcfg_reject_broken(type);
+               pci_mmcfg_reject_broken(early);
        }
 
        if ((pci_mmcfg_config_num == 0) ||
@@ -249,6 +416,16 @@ void __init pci_mmcfg_init(int type)
        }
 }
 
+void __init pci_mmcfg_early_init(void)
+{
+       __pci_mmcfg_init(1);
+}
+
+void __init pci_mmcfg_late_init(void)
+{
+       __pci_mmcfg_init(0);
+}
+
 static int __init pci_mmcfg_late_insert_resources(void)
 {
        /*
index 081816ada05792dc87d670db497a7ecf500534ba..f3c761dce6957118494ff8f2492edae9c7d9e651 100644 (file)
@@ -136,3 +136,7 @@ int __init pci_mmcfg_arch_init(void)
        raw_pci_ext_ops = &pci_mmcfg;
        return 1;
 }
+
+void __init pci_mmcfg_arch_free(void)
+{
+}
index 9207fd49233c1f120f6bbbd3e4b7c87f77c671b3..a1994163c99dd328e3c542d1bc0f5dd246e583cf 100644 (file)
@@ -127,7 +127,7 @@ static void __iomem * __init mcfg_ioremap(struct acpi_mcfg_allocation *cfg)
 int __init pci_mmcfg_arch_init(void)
 {
        int i;
-       pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) *
+       pci_mmcfg_virt = kzalloc(sizeof(*pci_mmcfg_virt) *
                                 pci_mmcfg_config_num, GFP_KERNEL);
        if (pci_mmcfg_virt == NULL) {
                printk(KERN_ERR "PCI: Can not allocate memory for mmconfig structures\n");
@@ -141,9 +141,29 @@ int __init pci_mmcfg_arch_init(void)
                        printk(KERN_ERR "PCI: Cannot map mmconfig aperture for "
                                        "segment %d\n",
                                pci_mmcfg_config[i].pci_segment);
+                       pci_mmcfg_arch_free();
                        return 0;
                }
        }
        raw_pci_ext_ops = &pci_mmcfg;
        return 1;
 }
+
+void __init pci_mmcfg_arch_free(void)
+{
+       int i;
+
+       if (pci_mmcfg_virt == NULL)
+               return;
+
+       for (i = 0; i < pci_mmcfg_config_num; ++i) {
+               if (pci_mmcfg_virt[i].virt) {
+                       iounmap(pci_mmcfg_virt[i].virt);
+                       pci_mmcfg_virt[i].virt = NULL;
+                       pci_mmcfg_virt[i].cfg = NULL;
+               }
+       }
+
+       kfree(pci_mmcfg_virt);
+       pci_mmcfg_virt = NULL;
+}
diff --git a/arch/x86/pci/mp_bus_to_node.c b/arch/x86/pci/mp_bus_to_node.c
new file mode 100644 (file)
index 0000000..0229439
--- /dev/null
@@ -0,0 +1,23 @@
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/topology.h>
+
+#define BUS_NR 256
+
+static unsigned char mp_bus_to_node[BUS_NR];
+
+void set_mp_bus_to_node(int busnum, int node)
+{
+       if (busnum >= 0 &&  busnum < BUS_NR)
+       mp_bus_to_node[busnum] = (unsigned char) node;
+}
+
+int get_mp_bus_to_node(int busnum)
+{
+       int node;
+
+       if (busnum < 0 || busnum > (BUS_NR - 1))
+               return 0;
+       node = mp_bus_to_node[busnum];
+       return node;
+}
diff --git a/arch/x86/pci/olpc.c b/arch/x86/pci/olpc.c
new file mode 100644 (file)
index 0000000..5e76365
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * Low-level PCI config space access for OLPC systems who lack the VSA
+ * PCI virtualization software.
+ *
+ * Copyright Â© 2006  Advanced Micro Devices, 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.
+ *
+ * The AMD Geode chipset (ie: GX2 processor, cs5536 I/O companion device)
+ * has some I/O functions (display, southbridge, sound, USB HCIs, etc)
+ * that more or less behave like PCI devices, but the hardware doesn't
+ * directly implement the PCI configuration space headers.  AMD provides
+ * "VSA" (Virtual System Architecture) software that emulates PCI config
+ * space for these devices, by trapping I/O accesses to PCI config register
+ * (CF8/CFC) and running some code in System Management Mode interrupt state.
+ * On the OLPC platform, we don't want to use that VSA code because
+ * (a) it slows down suspend/resume, and (b) recompiling it requires special
+ * compilers that are hard to get.  So instead of letting the complex VSA
+ * code simulate the PCI config registers for the on-chip devices, we
+ * just simulate them the easy way, by inserting the code into the
+ * pci_write_config and pci_read_config path.  Most of the config registers
+ * are read-only anyway, so the bulk of the simulation is just table lookup.
+ */
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <asm/olpc.h>
+#include <asm/geode.h>
+#include "pci.h"
+
+/*
+ * In the tables below, the first two line (8 longwords) are the
+ * size masks that are used when the higher level PCI code determines
+ * the size of the region by writing ~0 to a base address register
+ * and reading back the result.
+ *
+ * The following lines are the values that are read during normal
+ * PCI config access cycles, i.e. not after just having written
+ * ~0 to a base address register.
+ */
+
+static const uint32_t lxnb_hdr[] = {  /* dev 1 function 0 - devfn = 8 */
+       0x0,    0x0,    0x0,    0x0,
+       0x0,    0x0,    0x0,    0x0,
+
+       0x281022, 0x2200005, 0x6000021, 0x80f808,       /* AMD Vendor ID */
+       0x0,    0x0,    0x0,    0x0,   /* No virtual registers, hence no BAR */
+       0x0,    0x0,    0x0,    0x28100b,
+       0x0,    0x0,    0x0,    0x0,
+       0x0,    0x0,    0x0,    0x0,
+       0x0,    0x0,    0x0,    0x0,
+       0x0,    0x0,    0x0,    0x0,
+};
+
+static const uint32_t gxnb_hdr[] = {  /* dev 1 function 0 - devfn = 8 */
+       0xfffffffd, 0x0, 0x0,   0x0,
+       0x0,    0x0,    0x0,    0x0,
+
+       0x28100b, 0x2200005, 0x6000021, 0x80f808,       /* NSC Vendor ID */
+       0xac1d, 0x0,    0x0,    0x0,  /* I/O BAR - base of virtual registers */
+       0x0,    0x0,    0x0,    0x28100b,
+       0x0,    0x0,    0x0,    0x0,
+       0x0,    0x0,    0x0,    0x0,
+       0x0,    0x0,    0x0,    0x0,
+       0x0,    0x0,    0x0,    0x0,
+};
+
+static const uint32_t lxfb_hdr[] = {  /* dev 1 function 1 - devfn = 9 */
+       0xff000008, 0xffffc000, 0xffffc000, 0xffffc000,
+       0xffffc000,     0x0,    0x0,    0x0,
+
+       0x20811022, 0x2200003, 0x3000000, 0x0,          /* AMD Vendor ID */
+       0xfd000000, 0xfe000000, 0xfe004000, 0xfe008000, /* FB, GP, VG, DF */
+       0xfe00c000, 0x0, 0x0,   0x30100b,               /* VIP */
+       0x0,    0x0,    0x0,    0x10e,     /* INTA, IRQ14 for graphics accel */
+       0x0,    0x0,    0x0,    0x0,
+       0x3d0,  0x3c0,  0xa0000, 0x0,       /* VG IO, VG IO, EGA FB, MONO FB */
+       0x0,    0x0,    0x0,    0x0,
+};
+
+static const uint32_t gxfb_hdr[] = {  /* dev 1 function 1 - devfn = 9 */
+       0xff800008, 0xffffc000, 0xffffc000, 0xffffc000,
+       0x0,    0x0,    0x0,    0x0,
+
+       0x30100b, 0x2200003, 0x3000000, 0x0,            /* NSC Vendor ID */
+       0xfd000000, 0xfe000000, 0xfe004000, 0xfe008000, /* FB, GP, VG, DF */
+       0x0,    0x0,    0x0,    0x30100b,
+       0x0,    0x0,    0x0,    0x0,
+       0x0,    0x0,    0x0,    0x0,
+       0x3d0,  0x3c0,  0xa0000, 0x0,       /* VG IO, VG IO, EGA FB, MONO FB */
+       0x0,    0x0,    0x0,    0x0,
+};
+
+static const uint32_t aes_hdr[] = {    /* dev 1 function 2 - devfn = 0xa */
+       0xffffc000, 0x0, 0x0,   0x0,
+       0x0,    0x0,    0x0,    0x0,
+
+       0x20821022, 0x2a00006, 0x10100000, 0x8,         /* NSC Vendor ID */
+       0xfe010000, 0x0, 0x0,   0x0,                    /* AES registers */
+       0x0,    0x0,    0x0,    0x20821022,
+       0x0,    0x0,    0x0,    0x0,
+       0x0,    0x0,    0x0,    0x0,
+       0x0,    0x0,    0x0,    0x0,
+       0x0,    0x0,    0x0,    0x0,
+};
+
+
+static const uint32_t isa_hdr[] = {  /* dev f function 0 - devfn = 78 */
+       0xfffffff9, 0xffffff01, 0xffffffc1, 0xffffffe1,
+       0xffffff81, 0xffffffc1, 0x0, 0x0,
+
+       0x20901022, 0x2a00049, 0x6010003, 0x802000,
+       0x18b1, 0x1001, 0x1801, 0x1881, /* SMB-8   GPIO-256 MFGPT-64  IRQ-32 */
+       0x1401, 0x1841, 0x0,    0x20901022,             /* PMS-128 ACPI-64 */
+       0x0,    0x0,    0x0,    0x0,
+       0x0,    0x0,    0x0,    0x0,
+       0x0,    0x0,    0x0,    0xaa5b,                 /* IRQ steering */
+       0x0,    0x0,    0x0,    0x0,
+};
+
+static const uint32_t ac97_hdr[] = {  /* dev f function 3 - devfn = 7b */
+       0xffffff81, 0x0, 0x0,   0x0,
+       0x0,    0x0,    0x0,    0x0,
+
+       0x20931022, 0x2a00041, 0x4010001, 0x0,
+       0x1481, 0x0,    0x0,    0x0,                    /* I/O BAR-128 */
+       0x0,    0x0,    0x0,    0x20931022,
+       0x0,    0x0,    0x0,    0x205,                  /* IntB, IRQ5 */
+       0x0,    0x0,    0x0,    0x0,
+       0x0,    0x0,    0x0,    0x0,
+       0x0,    0x0,    0x0,    0x0,
+};
+
+static const uint32_t ohci_hdr[] = {  /* dev f function 4 - devfn = 7c */
+       0xfffff000, 0x0, 0x0,   0x0,
+       0x0,    0x0,    0x0,    0x0,
+
+       0x20941022, 0x2300006, 0xc031002, 0x0,
+       0xfe01a000, 0x0, 0x0,   0x0,                    /* MEMBAR-1000 */
+       0x0,    0x0,    0x0,    0x20941022,
+       0x0,    0x40,   0x0,    0x40a,                  /* CapPtr INT-D, IRQA */
+       0xc8020001, 0x0, 0x0,   0x0,    /* Capabilities - 40 is R/O,
+                                          44 is mask 8103 (power control) */
+       0x0,    0x0,    0x0,    0x0,
+       0x0,    0x0,    0x0,    0x0,
+};
+
+static const uint32_t ehci_hdr[] = {  /* dev f function 4 - devfn = 7d */
+       0xfffff000, 0x0, 0x0,   0x0,
+       0x0,    0x0,    0x0,    0x0,
+
+       0x20951022, 0x2300006, 0xc032002, 0x0,
+       0xfe01b000, 0x0, 0x0,   0x0,                    /* MEMBAR-1000 */
+       0x0,    0x0,    0x0,    0x20951022,
+       0x0,    0x40,   0x0,    0x40a,                  /* CapPtr INT-D, IRQA */
+       0xc8020001, 0x0, 0x0,   0x0,    /* Capabilities - 40 is R/O, 44 is
+                                          mask 8103 (power control) */
+#if 0
+       0x1,    0x40080000, 0x0, 0x0,   /* EECP - see EHCI spec section 2.1.7 */
+#endif
+       0x01000001, 0x0, 0x0,   0x0,    /* EECP - see EHCI spec section 2.1.7 */
+       0x2020, 0x0,    0x0,    0x0,    /* (EHCI page 8) 60 SBRN (R/O),
+                                          61 FLADJ (R/W), PORTWAKECAP  */
+};
+
+static uint32_t ff_loc = ~0;
+static uint32_t zero_loc;
+static int bar_probing;                /* Set after a write of ~0 to a BAR */
+static int is_lx;
+
+#define NB_SLOT 0x1    /* Northbridge - GX chip - Device 1 */
+#define SB_SLOT 0xf    /* Southbridge - CS5536 chip - Device F */
+
+static int is_simulated(unsigned int bus, unsigned int devfn)
+{
+       return (!bus && ((PCI_SLOT(devfn) == NB_SLOT) ||
+                       (PCI_SLOT(devfn) == SB_SLOT)));
+}
+
+static uint32_t *hdr_addr(const uint32_t *hdr, int reg)
+{
+       uint32_t addr;
+
+       /*
+        * This is a little bit tricky.  The header maps consist of
+        * 0x20 bytes of size masks, followed by 0x70 bytes of header data.
+        * In the normal case, when not probing a BAR's size, we want
+        * to access the header data, so we add 0x20 to the reg offset,
+        * thus skipping the size mask area.
+        * In the BAR probing case, we want to access the size mask for
+        * the BAR, so we subtract 0x10 (the config header offset for
+        * BAR0), and don't skip the size mask area.
+        */
+
+       addr = (uint32_t)hdr + reg + (bar_probing ? -0x10 : 0x20);
+
+       bar_probing = 0;
+       return (uint32_t *)addr;
+}
+
+static int pci_olpc_read(unsigned int seg, unsigned int bus,
+               unsigned int devfn, int reg, int len, uint32_t *value)
+{
+       uint32_t *addr;
+
+       /* Use the hardware mechanism for non-simulated devices */
+       if (!is_simulated(bus, devfn))
+               return pci_direct_conf1.read(seg, bus, devfn, reg, len, value);
+
+       /*
+        * No device has config registers past 0x70, so we save table space
+        * by not storing entries for the nonexistent registers
+        */
+       if (reg >= 0x70)
+               addr = &zero_loc;
+       else {
+               switch (devfn) {
+               case  0x8:
+                       addr = hdr_addr(is_lx ? lxnb_hdr : gxnb_hdr, reg);
+                       break;
+               case  0x9:
+                       addr = hdr_addr(is_lx ? lxfb_hdr : gxfb_hdr, reg);
+                       break;
+               case  0xa:
+                       addr = is_lx ? hdr_addr(aes_hdr, reg) : &ff_loc;
+                       break;
+               case 0x78:
+                       addr = hdr_addr(isa_hdr, reg);
+                       break;
+               case 0x7b:
+                       addr = hdr_addr(ac97_hdr, reg);
+                       break;
+               case 0x7c:
+                       addr = hdr_addr(ohci_hdr, reg);
+                       break;
+               case 0x7d:
+                       addr = hdr_addr(ehci_hdr, reg);
+                       break;
+               default:
+                       addr = &ff_loc;
+                       break;
+               }
+       }
+       switch (len) {
+       case 1:
+               *value = *(uint8_t *)addr;
+               break;
+       case 2:
+               *value = *(uint16_t *)addr;
+               break;
+       case 4:
+               *value = *addr;
+               break;
+       default:
+               BUG();
+       }
+
+       return 0;
+}
+
+static int pci_olpc_write(unsigned int seg, unsigned int bus,
+               unsigned int devfn, int reg, int len, uint32_t value)
+{
+       /* Use the hardware mechanism for non-simulated devices */
+       if (!is_simulated(bus, devfn))
+               return pci_direct_conf1.write(seg, bus, devfn, reg, len, value);
+
+       /* XXX we may want to extend this to simulate EHCI power management */
+
+       /*
+        * Mostly we just discard writes, but if the write is a size probe
+        * (i.e. writing ~0 to a BAR), we remember it and arrange to return
+        * the appropriate size mask on the next read.  This is cheating
+        * to some extent, because it depends on the fact that the next
+        * access after such a write will always be a read to the same BAR.
+        */
+
+       if ((reg >= 0x10) && (reg < 0x2c)) {
+               /* write is to a BAR */
+               if (value == ~0)
+                       bar_probing = 1;
+       } else {
+               /*
+                * No warning on writes to ROM BAR, CMD, LATENCY_TIMER,
+                * CACHE_LINE_SIZE, or PM registers.
+                */
+               if ((reg != PCI_ROM_ADDRESS) && (reg != PCI_COMMAND_MASTER) &&
+                               (reg != PCI_LATENCY_TIMER) &&
+                               (reg != PCI_CACHE_LINE_SIZE) && (reg != 0x44))
+                       printk(KERN_WARNING "OLPC PCI: Config write to devfn"
+                               " %x reg %x value %x\n", devfn, reg, value);
+       }
+
+       return 0;
+}
+
+static struct pci_raw_ops pci_olpc_conf = {
+       .read = pci_olpc_read,
+       .write = pci_olpc_write,
+};
+
+void __init pci_olpc_init(void)
+{
+       if (!machine_is_olpc() || olpc_has_vsa())
+               return;
+
+       printk(KERN_INFO "PCI: Using configuration type OLPC\n");
+       raw_pci_ops = &pci_olpc_conf;
+       is_lx = is_geode_lx();
+}
index c4bddaeff6194400539bad30890c528c20e9bf3f..c58805a92db5788e508482dd1579640c782750d0 100644 (file)
@@ -26,6 +26,7 @@
 #define PCI_ASSIGN_ALL_BUSSES  0x4000
 #define PCI_CAN_SKIP_ISA_ALIGN 0x8000
 #define PCI_USE__CRS           0x10000
+#define PCI_CHECK_ENABLE_AMD_MMCONF    0x20000
 
 extern unsigned int pci_probe;
 extern unsigned long pirq_table_addr;
@@ -97,11 +98,12 @@ extern struct pci_raw_ops pci_direct_conf1;
 extern int pci_direct_probe(void);
 extern void pci_direct_init(int type);
 extern void pci_pcbios_init(void);
-extern void pci_mmcfg_init(int type);
+extern void pci_olpc_init(void);
 
 /* pci-mmconfig.c */
 
 extern int __init pci_mmcfg_arch_init(void);
+extern void __init pci_mmcfg_arch_free(void);
 
 /*
  * AMD Fam10h CPUs are buggy, and cannot access MMIO config space
index ef63adadf7f4106ccded17d9370fd619a6557fb4..070ff8af3a21e45a338c95dad5d0e6d8bb74907c 100644 (file)
 #include <linux/thread_info.h>
 #include <linux/ptrace.h>
 #include <linux/mm.h>
+#include <linux/kbuild.h>
 
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
 
-#define DEFINE(sym, val) asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
 int main(void)
 {
        /* struct pt_regs */
index 55c5f1fc4f1fcd90c1f119a9bc0f58b46f446e83..66e55288178c0840ba44ff0a859fc72c817baf89 100644 (file)
@@ -53,7 +53,7 @@ EXPORT_SYMBOL(blk_queue_ordered);
 /*
  * Cache flushing for ordered writes handling
  */
-inline unsigned blk_ordered_cur_seq(struct request_queue *q)
+unsigned blk_ordered_cur_seq(struct request_queue *q)
 {
        if (!q->ordseq)
                return 0;
@@ -143,10 +143,8 @@ static void queue_flush(struct request_queue *q, unsigned which)
                end_io = post_flush_end_io;
        }
 
+       blk_rq_init(q, rq);
        rq->cmd_flags = REQ_HARDBARRIER;
-       rq_init(q, rq);
-       rq->elevator_private = NULL;
-       rq->elevator_private2 = NULL;
        rq->rq_disk = q->bar_rq.rq_disk;
        rq->end_io = end_io;
        q->prepare_flush_fn(q, rq);
@@ -167,14 +165,11 @@ static inline struct request *start_ordered(struct request_queue *q,
        blkdev_dequeue_request(rq);
        q->orig_bar_rq = rq;
        rq = &q->bar_rq;
-       rq->cmd_flags = 0;
-       rq_init(q, rq);
+       blk_rq_init(q, rq);
        if (bio_data_dir(q->orig_bar_rq->bio) == WRITE)
                rq->cmd_flags |= REQ_RW;
        if (q->ordered & QUEUE_ORDERED_FUA)
                rq->cmd_flags |= REQ_FUA;
-       rq->elevator_private = NULL;
-       rq->elevator_private2 = NULL;
        init_request_from_bio(rq, q->orig_bar_rq->bio);
        rq->end_io = bar_end_io;
 
index 2a438a93f7233d8bc2033956f23e3f436f0e1f44..5d09f8c56024011588ec1b89e90bff2033a150ca 100644 (file)
@@ -107,41 +107,21 @@ struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev)
 }
 EXPORT_SYMBOL(blk_get_backing_dev_info);
 
-/*
- * We can't just memset() the structure, since the allocation path
- * already stored some information in the request.
- */
-void rq_init(struct request_queue *q, struct request *rq)
+void blk_rq_init(struct request_queue *q, struct request *rq)
 {
+       memset(rq, 0, sizeof(*rq));
+
        INIT_LIST_HEAD(&rq->queuelist);
        INIT_LIST_HEAD(&rq->donelist);
        rq->q = q;
        rq->sector = rq->hard_sector = (sector_t) -1;
-       rq->nr_sectors = rq->hard_nr_sectors = 0;
-       rq->current_nr_sectors = rq->hard_cur_sectors = 0;
-       rq->bio = rq->biotail = NULL;
        INIT_HLIST_NODE(&rq->hash);
        RB_CLEAR_NODE(&rq->rb_node);
-       rq->rq_disk = NULL;
-       rq->nr_phys_segments = 0;
-       rq->nr_hw_segments = 0;
-       rq->ioprio = 0;
-       rq->special = NULL;
-       rq->buffer = NULL;
+       rq->cmd = rq->__cmd;
        rq->tag = -1;
-       rq->errors = 0;
        rq->ref_count = 1;
-       rq->cmd_len = 0;
-       memset(rq->cmd, 0, sizeof(rq->cmd));
-       rq->data_len = 0;
-       rq->extra_len = 0;
-       rq->sense_len = 0;
-       rq->data = NULL;
-       rq->sense = NULL;
-       rq->end_io = NULL;
-       rq->end_io_data = NULL;
-       rq->next_rq = NULL;
 }
+EXPORT_SYMBOL(blk_rq_init);
 
 static void req_bio_endio(struct request *rq, struct bio *bio,
                          unsigned int nbytes, int error)
@@ -194,7 +174,7 @@ void blk_dump_rq_flags(struct request *rq, char *msg)
 
        if (blk_pc_request(rq)) {
                printk(KERN_INFO "  cdb: ");
-               for (bit = 0; bit < sizeof(rq->cmd); bit++)
+               for (bit = 0; bit < BLK_MAX_CDB; bit++)
                        printk("%02x ", rq->cmd[bit]);
                printk("\n");
        }
@@ -220,7 +200,8 @@ void blk_plug_device(struct request_queue *q)
        if (blk_queue_stopped(q))
                return;
 
-       if (!test_and_set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) {
+       if (!test_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) {
+               __set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags);
                mod_timer(&q->unplug_timer, jiffies + q->unplug_delay);
                blk_add_trace_generic(q, NULL, 0, BLK_TA_PLUG);
        }
@@ -235,9 +216,10 @@ int blk_remove_plug(struct request_queue *q)
 {
        WARN_ON(!irqs_disabled());
 
-       if (!test_and_clear_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags))
+       if (!test_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags))
                return 0;
 
+       queue_flag_clear(QUEUE_FLAG_PLUGGED, q);
        del_timer(&q->unplug_timer);
        return 1;
 }
@@ -333,15 +315,16 @@ void blk_start_queue(struct request_queue *q)
 {
        WARN_ON(!irqs_disabled());
 
-       clear_bit(QUEUE_FLAG_STOPPED, &q->queue_flags);
+       queue_flag_clear(QUEUE_FLAG_STOPPED, q);
 
        /*
         * one level of recursion is ok and is much faster than kicking
         * the unplug handling
         */
-       if (!test_and_set_bit(QUEUE_FLAG_REENTER, &q->queue_flags)) {
+       if (!test_bit(QUEUE_FLAG_REENTER, &q->queue_flags)) {
+               queue_flag_set(QUEUE_FLAG_REENTER, q);
                q->request_fn(q);
-               clear_bit(QUEUE_FLAG_REENTER, &q->queue_flags);
+               queue_flag_clear(QUEUE_FLAG_REENTER, q);
        } else {
                blk_plug_device(q);
                kblockd_schedule_work(&q->unplug_work);
@@ -366,7 +349,7 @@ EXPORT_SYMBOL(blk_start_queue);
 void blk_stop_queue(struct request_queue *q)
 {
        blk_remove_plug(q);
-       set_bit(QUEUE_FLAG_STOPPED, &q->queue_flags);
+       queue_flag_set(QUEUE_FLAG_STOPPED, q);
 }
 EXPORT_SYMBOL(blk_stop_queue);
 
@@ -395,11 +378,8 @@ EXPORT_SYMBOL(blk_sync_queue);
  * blk_run_queue - run a single device queue
  * @q: The queue to run
  */
-void blk_run_queue(struct request_queue *q)
+void __blk_run_queue(struct request_queue *q)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(q->queue_lock, flags);
        blk_remove_plug(q);
 
        /*
@@ -407,15 +387,28 @@ void blk_run_queue(struct request_queue *q)
         * handling reinvoke the handler shortly if we already got there.
         */
        if (!elv_queue_empty(q)) {
-               if (!test_and_set_bit(QUEUE_FLAG_REENTER, &q->queue_flags)) {
+               if (!test_bit(QUEUE_FLAG_REENTER, &q->queue_flags)) {
+                       queue_flag_set(QUEUE_FLAG_REENTER, q);
                        q->request_fn(q);
-                       clear_bit(QUEUE_FLAG_REENTER, &q->queue_flags);
+                       queue_flag_clear(QUEUE_FLAG_REENTER, q);
                } else {
                        blk_plug_device(q);
                        kblockd_schedule_work(&q->unplug_work);
                }
        }
+}
+EXPORT_SYMBOL(__blk_run_queue);
+
+/**
+ * blk_run_queue - run a single device queue
+ * @q: The queue to run
+ */
+void blk_run_queue(struct request_queue *q)
+{
+       unsigned long flags;
 
+       spin_lock_irqsave(q->queue_lock, flags);
+       __blk_run_queue(q);
        spin_unlock_irqrestore(q->queue_lock, flags);
 }
 EXPORT_SYMBOL(blk_run_queue);
@@ -428,7 +421,7 @@ void blk_put_queue(struct request_queue *q)
 void blk_cleanup_queue(struct request_queue *q)
 {
        mutex_lock(&q->sysfs_lock);
-       set_bit(QUEUE_FLAG_DEAD, &q->queue_flags);
+       queue_flag_set_unlocked(QUEUE_FLAG_DEAD, q);
        mutex_unlock(&q->sysfs_lock);
 
        if (q->elevator)
@@ -607,6 +600,8 @@ blk_alloc_request(struct request_queue *q, int rw, int priv, gfp_t gfp_mask)
        if (!rq)
                return NULL;
 
+       blk_rq_init(q, rq);
+
        /*
         * first three bits are identical in rq->cmd_flags and bio->bi_rw,
         * see bio.h and blkdev.h
@@ -789,8 +784,6 @@ rq_starved:
        if (ioc_batching(q, ioc))
                ioc->nr_batch_requests--;
 
-       rq_init(q, rq);
-
        blk_add_trace_generic(q, bio, rw, BLK_TA_GETRQ);
 out:
        return rq;
index 3c942bd6422a2ba639597ace2ad9f3768ccf1456..0b1af5a3537ca0728407c8acfedfaba44338cd19 100644 (file)
@@ -255,10 +255,18 @@ EXPORT_SYMBOL(blk_rq_unmap_user);
  * @kbuf:      the kernel buffer
  * @len:       length of user data
  * @gfp_mask:  memory allocation flags
+ *
+ * Description:
+ *    Data will be mapped directly if possible. Otherwise a bounce
+ *    buffer is used.
  */
 int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
                    unsigned int len, gfp_t gfp_mask)
 {
+       unsigned long kaddr;
+       unsigned int alignment;
+       int reading = rq_data_dir(rq) == READ;
+       int do_copy = 0;
        struct bio *bio;
 
        if (len > (q->max_hw_sectors << 9))
@@ -266,13 +274,24 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf,
        if (!len || !kbuf)
                return -EINVAL;
 
-       bio = bio_map_kern(q, kbuf, len, gfp_mask);
+       kaddr = (unsigned long)kbuf;
+       alignment = queue_dma_alignment(q) | q->dma_pad_mask;
+       do_copy = ((kaddr & alignment) || (len & alignment));
+
+       if (do_copy)
+               bio = bio_copy_kern(q, kbuf, len, gfp_mask, reading);
+       else
+               bio = bio_map_kern(q, kbuf, len, gfp_mask);
+
        if (IS_ERR(bio))
                return PTR_ERR(bio);
 
        if (rq_data_dir(rq) == WRITE)
                bio->bi_rw |= (1 << BIO_RW);
 
+       if (do_copy)
+               rq->cmd_flags |= REQ_COPY_USER;
+
        blk_rq_bio_prep(q, rq, bio);
        blk_queue_bounce(q, &rq->bio);
        rq->buffer = rq->data = NULL;
index b5c5c4a9e3f08d051a25d44e92689580d19cbce5..73b23562af20086f3a8623df6e9f32561ae330b5 100644 (file)
@@ -55,7 +55,7 @@ void blk_recalc_rq_segments(struct request *rq)
        if (!rq->bio)
                return;
 
-       cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER);
+       cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
        hw_seg_size = seg_size = 0;
        phys_size = hw_size = nr_phys_segs = nr_hw_segs = 0;
        rq_for_each_segment(bv, rq, iter) {
@@ -128,7 +128,7 @@ EXPORT_SYMBOL(blk_recount_segments);
 static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
                                   struct bio *nxt)
 {
-       if (!(q->queue_flags & (1 << QUEUE_FLAG_CLUSTER)))
+       if (!test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags))
                return 0;
 
        if (!BIOVEC_PHYS_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt)))
@@ -175,7 +175,7 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
        int nsegs, cluster;
 
        nsegs = 0;
-       cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER);
+       cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
 
        /*
         * for each bio in rq
index 5713f7e5cbd266c6db06a8b5311b0ffa97d225b2..6089384ab06499becc951478d06dda2e22aa7e00 100644 (file)
@@ -14,7 +14,6 @@ unsigned long blk_max_low_pfn;
 EXPORT_SYMBOL(blk_max_low_pfn);
 
 unsigned long blk_max_pfn;
-EXPORT_SYMBOL(blk_max_pfn);
 
 /**
  * blk_queue_prep_rq - set a prepare_request function for queue
@@ -288,7 +287,7 @@ void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b)
        t->max_segment_size = min(t->max_segment_size, b->max_segment_size);
        t->hardsect_size = max(t->hardsect_size, b->hardsect_size);
        if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags))
-               clear_bit(QUEUE_FLAG_CLUSTER, &t->queue_flags);
+               queue_flag_clear(QUEUE_FLAG_CLUSTER, t);
 }
 EXPORT_SYMBOL(blk_queue_stack_limits);
 
index fc41d83be22bb02bab61f09b4b356dbba4697a05..e85c4013e8a29a5924c4657447a2b6611eb17702 100644 (file)
@@ -135,6 +135,25 @@ static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page)
        return queue_var_show(max_hw_sectors_kb, (page));
 }
 
+static ssize_t queue_nomerges_show(struct request_queue *q, char *page)
+{
+       return queue_var_show(blk_queue_nomerges(q), page);
+}
+
+static ssize_t queue_nomerges_store(struct request_queue *q, const char *page,
+                                   size_t count)
+{
+       unsigned long nm;
+       ssize_t ret = queue_var_store(&nm, page, count);
+
+       if (nm)
+              set_bit(QUEUE_FLAG_NOMERGES, &q->queue_flags);
+       else
+              clear_bit(QUEUE_FLAG_NOMERGES, &q->queue_flags);
+
+       return ret;
+}
+
 
 static struct queue_sysfs_entry queue_requests_entry = {
        .attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
@@ -170,6 +189,12 @@ static struct queue_sysfs_entry queue_hw_sector_size_entry = {
        .show = queue_hw_sector_size_show,
 };
 
+static struct queue_sysfs_entry queue_nomerges_entry = {
+       .attr = {.name = "nomerges", .mode = S_IRUGO | S_IWUSR },
+       .show = queue_nomerges_show,
+       .store = queue_nomerges_store,
+};
+
 static struct attribute *default_attrs[] = {
        &queue_requests_entry.attr,
        &queue_ra_entry.attr,
@@ -177,6 +202,7 @@ static struct attribute *default_attrs[] = {
        &queue_max_sectors_entry.attr,
        &queue_iosched_entry.attr,
        &queue_hw_sector_size_entry.attr,
+       &queue_nomerges_entry.attr,
        NULL,
 };
 
index 4780a46ce2346898953085a6f4079c7734dcbaf7..e176ddbe599e23796c004e3d0354cbc4c6b337cf 100644 (file)
@@ -70,7 +70,7 @@ void __blk_queue_free_tags(struct request_queue *q)
        __blk_free_tags(bqt);
 
        q->queue_tags = NULL;
-       q->queue_flags &= ~(1 << QUEUE_FLAG_QUEUED);
+       queue_flag_clear(QUEUE_FLAG_QUEUED, q);
 }
 
 /**
@@ -98,7 +98,7 @@ EXPORT_SYMBOL(blk_free_tags);
  **/
 void blk_queue_free_tags(struct request_queue *q)
 {
-       clear_bit(QUEUE_FLAG_QUEUED, &q->queue_flags);
+       queue_flag_clear(QUEUE_FLAG_QUEUED, q);
 }
 EXPORT_SYMBOL(blk_queue_free_tags);
 
@@ -188,7 +188,7 @@ int blk_queue_init_tags(struct request_queue *q, int depth,
                rc = blk_queue_resize_tags(q, depth);
                if (rc)
                        return rc;
-               set_bit(QUEUE_FLAG_QUEUED, &q->queue_flags);
+               queue_flag_set(QUEUE_FLAG_QUEUED, q);
                return 0;
        } else
                atomic_inc(&tags->refcnt);
@@ -197,7 +197,7 @@ int blk_queue_init_tags(struct request_queue *q, int depth,
         * assign it, all done
         */
        q->queue_tags = tags;
-       q->queue_flags |= (1 << QUEUE_FLAG_QUEUED);
+       queue_flag_set(QUEUE_FLAG_QUEUED, q);
        INIT_LIST_HEAD(&q->tag_busy_list);
        return 0;
 fail:
index ec9120fb789a67c560df9c12e38dc8e0cc46a008..59776ab4742aae29678d34886665dc437dadd00c 100644 (file)
@@ -10,7 +10,6 @@
 extern struct kmem_cache *blk_requestq_cachep;
 extern struct kobj_type blk_queue_ktype;
 
-void rq_init(struct request_queue *q, struct request *rq);
 void init_request_from_bio(struct request *req, struct bio *bio);
 void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
                        struct bio *bio);
index 88318c383608defa5018bdfa929918c767c8d7fa..ac5310ef8270984e32799e0524917abf4246853a 100644 (file)
@@ -69,7 +69,7 @@ static int elv_iosched_allow_merge(struct request *rq, struct bio *bio)
 /*
  * can we safely merge with this request?
  */
-inline int elv_rq_merge_ok(struct request *rq, struct bio *bio)
+int elv_rq_merge_ok(struct request *rq, struct bio *bio)
 {
        if (!rq_mergeable(rq))
                return 0;
@@ -488,6 +488,9 @@ int elv_merge(struct request_queue *q, struct request **req, struct bio *bio)
                }
        }
 
+       if (blk_queue_nomerges(q))
+               return ELEVATOR_NO_MERGE;
+
        /*
         * See if our hash lookup can find a potential backmerge.
         */
@@ -1070,7 +1073,7 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
         */
        spin_lock_irq(q->queue_lock);
 
-       set_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
+       queue_flag_set(QUEUE_FLAG_ELVSWITCH, q);
 
        elv_drain_elevator(q);
 
@@ -1104,7 +1107,10 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
         * finally exit old elevator and turn off BYPASS.
         */
        elevator_exit(old_elevator);
-       clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
+       spin_lock_irq(q->queue_lock);
+       queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
+       spin_unlock_irq(q->queue_lock);
+
        return 1;
 
 fail_register:
@@ -1115,7 +1121,11 @@ fail_register:
        elevator_exit(e);
        q->elevator = old_elevator;
        elv_register_queue(q);
-       clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
+
+       spin_lock_irq(q->queue_lock);
+       queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
+       spin_unlock_irq(q->queue_lock);
+
        return 0;
 }
 
index 00da5219ee37c02a066d45e6ceefa65d9606d5e6..fda9c7a63c29e3ecc323fa373365843771860ec4 100644 (file)
@@ -182,11 +182,17 @@ static int exact_lock(dev_t devt, void *data)
  */
 void add_disk(struct gendisk *disk)
 {
+       struct backing_dev_info *bdi;
+
        disk->flags |= GENHD_FL_UP;
        blk_register_region(MKDEV(disk->major, disk->first_minor),
                            disk->minors, NULL, exact_match, exact_lock, disk);
        register_disk(disk);
        blk_register_queue(disk);
+
+       bdi = &disk->queue->backing_dev_info;
+       bdi_register_dev(bdi, MKDEV(disk->major, disk->first_minor));
+       sysfs_create_link(&disk->dev.kobj, &bdi->dev->kobj, "bdi");
 }
 
 EXPORT_SYMBOL(add_disk);
@@ -194,6 +200,8 @@ EXPORT_SYMBOL(del_gendisk); /* in partitions/check.c */
 
 void unlink_gendisk(struct gendisk *disk)
 {
+       sysfs_remove_link(&disk->dev.kobj, "bdi");
+       bdi_unregister(&disk->queue->backing_dev_info);
        blk_unregister_queue(disk);
        blk_unregister_region(MKDEV(disk->major, disk->first_minor),
                              disk->minors);
index a2c3a936ebf98e1481346e76a7ef268b803c76ea..ffa3720e6ca05de7830a466664327deed289aa12 100644 (file)
@@ -217,8 +217,6 @@ EXPORT_SYMBOL_GPL(blk_verify_command);
 static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
                             struct sg_io_hdr *hdr, int has_write_perm)
 {
-       memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
-
        if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len))
                return -EFAULT;
        if (blk_verify_command(rq->cmd, has_write_perm))
@@ -531,7 +529,6 @@ static int __blk_send_generic(struct request_queue *q, struct gendisk *bd_disk,
        rq->data_len = 0;
        rq->extra_len = 0;
        rq->timeout = BLK_DEFAULT_SG_TIMEOUT;
-       memset(rq->cmd, 0, sizeof(rq->cmd));
        rq->cmd[0] = cmd;
        rq->cmd[4] = data;
        rq->cmd_len = 6;
index 80f0ec91e2cf3fd04f6076661c6e223ec931a5db..59f33fa6af3ea8f332bc8e23682eda538a0acb08 100644 (file)
@@ -84,6 +84,8 @@ source "drivers/memstick/Kconfig"
 
 source "drivers/leds/Kconfig"
 
+source "drivers/accessibility/Kconfig"
+
 source "drivers/infiniband/Kconfig"
 
 source "drivers/edac/Kconfig"
index e5e394a7e6c0873be132cb10086b7a89c93332d7..f65deda72d6102636e47554c9864d529df27a258 100644 (file)
@@ -70,6 +70,7 @@ obj-$(CONFIG_WATCHDOG)                += watchdog/
 obj-$(CONFIG_PHONE)            += telephony/
 obj-$(CONFIG_MD)               += md/
 obj-$(CONFIG_BT)               += bluetooth/
+obj-$(CONFIG_ACCESSIBILITY)    += accessibility/
 obj-$(CONFIG_ISDN)             += isdn/
 obj-$(CONFIG_EDAC)             += edac/
 obj-$(CONFIG_MCA)              += mca/
diff --git a/drivers/accessibility/Kconfig b/drivers/accessibility/Kconfig
new file mode 100644 (file)
index 0000000..1264c4b
--- /dev/null
@@ -0,0 +1,23 @@
+menuconfig ACCESSIBILITY
+       bool "Accessibility support"
+       ---help---
+         Enable a submenu where accessibility items may be enabled.
+
+         If unsure, say N.
+
+if ACCESSIBILITY
+config A11Y_BRAILLE_CONSOLE
+       bool "Console on braille device"
+       depends on VT
+       depends on SERIAL_CORE_CONSOLE
+       ---help---
+         Enables console output on a braille device connected to a 8250
+         serial port. For now only the VisioBraille device is supported.
+
+         To actually enable it, you need to pass option
+         console=brl,ttyS0
+         to the kernel. Options are the same as for serial console.
+
+         If unsure, say N.
+
+endif # ACCESSIBILITY
diff --git a/drivers/accessibility/Makefile b/drivers/accessibility/Makefile
new file mode 100644 (file)
index 0000000..72b01a4
--- /dev/null
@@ -0,0 +1 @@
+obj-y                          += braille/
diff --git a/drivers/accessibility/braille/Makefile b/drivers/accessibility/braille/Makefile
new file mode 100644 (file)
index 0000000..2e9f16c
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_A11Y_BRAILLE_CONSOLE)             += braille_console.o
diff --git a/drivers/accessibility/braille/braille_console.c b/drivers/accessibility/braille/braille_console.c
new file mode 100644 (file)
index 0000000..0a5f6b2
--- /dev/null
@@ -0,0 +1,397 @@
+/*
+ * Minimalistic braille device kernel support.
+ *
+ * By default, shows console messages on the braille device.
+ * Pressing Insert switches to VC browsing.
+ *
+ *  Copyright (C) Samuel Thibault <samuel.thibault@ens-lyon.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.
+ *
+ * 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 the program ; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/autoconf.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/console.h>
+#include <linux/notifier.h>
+
+#include <linux/selection.h>
+#include <linux/vt_kern.h>
+#include <linux/consolemap.h>
+
+#include <linux/keyboard.h>
+#include <linux/kbd_kern.h>
+#include <linux/input.h>
+
+MODULE_AUTHOR("samuel.thibault@ens-lyon.org");
+MODULE_DESCRIPTION("braille device");
+MODULE_LICENSE("GPL");
+
+/*
+ * Braille device support part.
+ */
+
+/* Emit various sounds */
+static int sound;
+module_param(sound, bool, 0);
+MODULE_PARM_DESC(sound, "emit sounds");
+
+static void beep(unsigned int freq)
+{
+       if (sound)
+               kd_mksound(freq, HZ/10);
+}
+
+/* mini console */
+#define WIDTH 40
+#define BRAILLE_KEY KEY_INSERT
+static u16 console_buf[WIDTH];
+static int console_cursor;
+
+/* mini view of VC */
+static int vc_x, vc_y, lastvc_x, lastvc_y;
+
+/* show console ? (or show VC) */
+static int console_show = 1;
+/* pending newline ? */
+static int console_newline = 1;
+static int lastVC = -1;
+
+static struct console *braille_co;
+
+/* Very VisioBraille-specific */
+static void braille_write(u16 *buf)
+{
+       static u16 lastwrite[WIDTH];
+       unsigned char data[1 + 1 + 2*WIDTH + 2 + 1], csum = 0, *c;
+       u16 out;
+       int i;
+
+       if (!braille_co)
+               return;
+
+       if (!memcmp(lastwrite, buf, WIDTH * sizeof(*buf)))
+               return;
+       memcpy(lastwrite, buf, WIDTH * sizeof(*buf));
+
+#define SOH 1
+#define STX 2
+#define ETX 2
+#define EOT 4
+#define ENQ 5
+       data[0] = STX;
+       data[1] = '>';
+       csum ^= '>';
+       c = &data[2];
+       for (i = 0; i < WIDTH; i++) {
+               out = buf[i];
+               if (out >= 0x100)
+                       out = '?';
+               else if (out == 0x00)
+                       out = ' ';
+               csum ^= out;
+               if (out <= 0x05) {
+                       *c++ = SOH;
+                       out |= 0x40;
+               }
+               *c++ = out;
+       }
+
+       if (csum <= 0x05) {
+               *c++ = SOH;
+               csum |= 0x40;
+       }
+       *c++ = csum;
+       *c++ = ETX;
+
+       braille_co->write(braille_co, data, c - data);
+}
+
+/* Follow the VC cursor*/
+static void vc_follow_cursor(struct vc_data *vc)
+{
+       vc_x = vc->vc_x - (vc->vc_x % WIDTH);
+       vc_y = vc->vc_y;
+       lastvc_x = vc->vc_x;
+       lastvc_y = vc->vc_y;
+}
+
+/* Maybe the VC cursor moved, if so follow it */
+static void vc_maybe_cursor_moved(struct vc_data *vc)
+{
+       if (vc->vc_x != lastvc_x || vc->vc_y != lastvc_y)
+               vc_follow_cursor(vc);
+}
+
+/* Show portion of VC at vc_x, vc_y */
+static void vc_refresh(struct vc_data *vc)
+{
+       u16 buf[WIDTH];
+       int i;
+
+       for (i = 0; i < WIDTH; i++) {
+               u16 glyph = screen_glyph(vc,
+                               2 * (vc_x + i) + vc_y * vc->vc_size_row);
+               buf[i] = inverse_translate(vc, glyph, 1);
+       }
+       braille_write(buf);
+}
+
+/*
+ * Link to keyboard
+ */
+
+static int keyboard_notifier_call(struct notifier_block *blk,
+                                 unsigned long code, void *_param)
+{
+       struct keyboard_notifier_param *param = _param;
+       struct vc_data *vc = param->vc;
+       int ret = NOTIFY_OK;
+
+       if (!param->down)
+               return ret;
+
+       switch (code) {
+       case KBD_KEYCODE:
+               if (console_show) {
+                       if (param->value == BRAILLE_KEY) {
+                               console_show = 0;
+                               beep(880);
+                               vc_maybe_cursor_moved(vc);
+                               vc_refresh(vc);
+                               ret = NOTIFY_STOP;
+                       }
+               } else {
+                       ret = NOTIFY_STOP;
+                       switch (param->value) {
+                       case KEY_INSERT:
+                               beep(440);
+                               console_show = 1;
+                               lastVC = -1;
+                               braille_write(console_buf);
+                               break;
+                       case KEY_LEFT:
+                               if (vc_x > 0) {
+                                       vc_x -= WIDTH;
+                                       if (vc_x < 0)
+                                               vc_x = 0;
+                               } else if (vc_y >= 1) {
+                                       beep(880);
+                                       vc_y--;
+                                       vc_x = vc->vc_cols-WIDTH;
+                               } else
+                                       beep(220);
+                               break;
+                       case KEY_RIGHT:
+                               if (vc_x + WIDTH < vc->vc_cols) {
+                                       vc_x += WIDTH;
+                               } else if (vc_y + 1 < vc->vc_rows) {
+                                       beep(880);
+                                       vc_y++;
+                                       vc_x = 0;
+                               } else
+                                       beep(220);
+                               break;
+                       case KEY_DOWN:
+                               if (vc_y + 1 < vc->vc_rows)
+                                       vc_y++;
+                               else
+                                       beep(220);
+                               break;
+                       case KEY_UP:
+                               if (vc_y >= 1)
+                                       vc_y--;
+                               else
+                                       beep(220);
+                               break;
+                       case KEY_HOME:
+                               vc_follow_cursor(vc);
+                               break;
+                       case KEY_PAGEUP:
+                               vc_x = 0;
+                               vc_y = 0;
+                               break;
+                       case KEY_PAGEDOWN:
+                               vc_x = 0;
+                               vc_y = vc->vc_rows-1;
+                               break;
+                       default:
+                               ret = NOTIFY_OK;
+                               break;
+                       }
+                       if (ret == NOTIFY_STOP)
+                               vc_refresh(vc);
+               }
+               break;
+       case KBD_POST_KEYSYM:
+       {
+               unsigned char type = KTYP(param->value) - 0xf0;
+               if (type == KT_SPEC) {
+                       unsigned char val = KVAL(param->value);
+                       int on_off = -1;
+
+                       switch (val) {
+                       case KVAL(K_CAPS):
+                               on_off = vc_kbd_led(kbd_table + fg_console,
+                                               VC_CAPSLOCK);
+                               break;
+                       case KVAL(K_NUM):
+                               on_off = vc_kbd_led(kbd_table + fg_console,
+                                               VC_NUMLOCK);
+                               break;
+                       case KVAL(K_HOLD):
+                               on_off = vc_kbd_led(kbd_table + fg_console,
+                                               VC_SCROLLOCK);
+                               break;
+                       }
+                       if (on_off == 1)
+                               beep(880);
+                       else if (on_off == 0)
+                               beep(440);
+               }
+       }
+       case KBD_UNBOUND_KEYCODE:
+       case KBD_UNICODE:
+       case KBD_KEYSYM:
+               /* Unused */
+               break;
+       }
+       return ret;
+}
+
+static struct notifier_block keyboard_notifier_block = {
+       .notifier_call = keyboard_notifier_call,
+};
+
+static int vt_notifier_call(struct notifier_block *blk,
+                           unsigned long code, void *_param)
+{
+       struct vt_notifier_param *param = _param;
+       struct vc_data *vc = param->vc;
+       switch (code) {
+       case VT_ALLOCATE:
+               break;
+       case VT_DEALLOCATE:
+               break;
+       case VT_WRITE:
+       {
+               unsigned char c = param->c;
+               if (vc->vc_num != fg_console)
+                       break;
+               switch (c) {
+               case '\b':
+               case 127:
+                       if (console_cursor > 0) {
+                               console_cursor--;
+                               console_buf[console_cursor] = ' ';
+                       }
+                       break;
+               case '\n':
+               case '\v':
+               case '\f':
+               case '\r':
+                       console_newline = 1;
+                       break;
+               case '\t':
+                       c = ' ';
+                       /* Fallthrough */
+               default:
+                       if (c < 32)
+                               /* Ignore other control sequences */
+                               break;
+                       if (console_newline) {
+                               memset(console_buf, 0, sizeof(console_buf));
+                               console_cursor = 0;
+                               console_newline = 0;
+                       }
+                       if (console_cursor == WIDTH)
+                               memmove(console_buf, &console_buf[1],
+                                       (WIDTH-1) * sizeof(*console_buf));
+                       else
+                               console_cursor++;
+                       console_buf[console_cursor-1] = c;
+                       break;
+               }
+               if (console_show)
+                       braille_write(console_buf);
+               else {
+                       vc_maybe_cursor_moved(vc);
+                       vc_refresh(vc);
+               }
+               break;
+       }
+       case VT_UPDATE:
+               /* Maybe a VT switch, flush */
+               if (console_show) {
+                       if (vc->vc_num != lastVC) {
+                               lastVC = vc->vc_num;
+                               memset(console_buf, 0, sizeof(console_buf));
+                               console_cursor = 0;
+                               braille_write(console_buf);
+                       }
+               } else {
+                       vc_maybe_cursor_moved(vc);
+                       vc_refresh(vc);
+               }
+               break;
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block vt_notifier_block = {
+       .notifier_call = vt_notifier_call,
+};
+
+/*
+ * Called from printk.c when console=brl is given
+ */
+
+int braille_register_console(struct console *console, int index,
+               char *console_options, char *braille_options)
+{
+       int ret;
+       if (!console_options)
+               /* Only support VisioBraille for now */
+               console_options = "57600o8";
+       if (braille_co)
+               return -ENODEV;
+       if (console->setup) {
+               ret = console->setup(console, console_options);
+               if (ret != 0)
+                       return ret;
+       }
+       console->flags |= CON_ENABLED;
+       console->index = index;
+       braille_co = console;
+       return 0;
+}
+
+int braille_unregister_console(struct console *console)
+{
+       if (braille_co != console)
+               return -EINVAL;
+       braille_co = NULL;
+       return 0;
+}
+
+static int __init braille_init(void)
+{
+       register_keyboard_notifier(&keyboard_notifier_block);
+       register_vt_notifier(&vt_notifier_block);
+       return 0;
+}
+
+console_initcall(braille_init);
index 43a95e5640debc27496f518a2170b4b2a5090b2c..5b73f6a2cd86c839d36ed8c9cb83bb5659f0cc04 100644 (file)
@@ -92,6 +92,7 @@ struct acpi_ac {
 
 #ifdef CONFIG_ACPI_PROCFS_POWER
 static const struct file_operations acpi_ac_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_ac_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -195,16 +196,11 @@ static int acpi_ac_add_fs(struct acpi_device *device)
        }
 
        /* 'state' [R] */
-       entry = create_proc_entry(ACPI_AC_FILE_STATE,
-                                 S_IRUGO, acpi_device_dir(device));
+       entry = proc_create_data(ACPI_AC_FILE_STATE,
+                                S_IRUGO, acpi_device_dir(device),
+                                &acpi_ac_fops, acpi_driver_data(device));
        if (!entry)
                return -ENODEV;
-       else {
-               entry->proc_fops = &acpi_ac_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
-
        return 0;
 }
 
index d5729d5dc1904564921cede6f7f80d72b987205c..b1c723f9f58d1fce3861730870b58550fe13f6a2 100644 (file)
@@ -741,15 +741,13 @@ static int acpi_battery_add_fs(struct acpi_device *device)
        }
 
        for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
-               entry = create_proc_entry(acpi_battery_file[i].name,
-                                 acpi_battery_file[i].mode, acpi_device_dir(device));
+               entry = proc_create_data(acpi_battery_file[i].name,
+                                        acpi_battery_file[i].mode,
+                                        acpi_device_dir(device),
+                                        &acpi_battery_file[i].ops,
+                                        acpi_driver_data(device));
                if (!entry)
                        return -ENODEV;
-               else {
-                       entry->proc_fops = &acpi_battery_file[i].ops;
-                       entry->data = acpi_driver_data(device);
-                       entry->owner = THIS_MODULE;
-               }
        }
        return 0;
 }
index 2d1955c118337fae68004ccaf3f7d3f3238b9cba..a6dbcf4d9ef57dcdfa93ecc045e51fd60a4b20d1 100644 (file)
@@ -35,6 +35,7 @@
 #ifdef CONFIG_X86
 #include <asm/mpspec.h>
 #endif
+#include <linux/pci.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
@@ -784,6 +785,7 @@ static int __init acpi_init(void)
        result = acpi_bus_init();
 
        if (!result) {
+               pci_mmcfg_late_init();
                if (!(pm_flags & PM_APM))
                        pm_flags |= PM_ACPI;
                else {
index 6c5da83cdb6807be36db10253bd42c2c332c0402..1dfec413588ca6e07ba06f51b69b7ea431906a2b 100644 (file)
@@ -102,6 +102,7 @@ struct acpi_button {
 };
 
 static const struct file_operations acpi_button_info_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_button_info_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -109,6 +110,7 @@ static const struct file_operations acpi_button_info_fops = {
 };
 
 static const struct file_operations acpi_button_state_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_button_state_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -207,27 +209,21 @@ static int acpi_button_add_fs(struct acpi_device *device)
        acpi_device_dir(device)->owner = THIS_MODULE;
 
        /* 'info' [R] */
-       entry = create_proc_entry(ACPI_BUTTON_FILE_INFO,
-                                 S_IRUGO, acpi_device_dir(device));
+       entry = proc_create_data(ACPI_BUTTON_FILE_INFO,
+                                S_IRUGO, acpi_device_dir(device),
+                                &acpi_button_info_fops,
+                                acpi_driver_data(device));
        if (!entry)
                return -ENODEV;
-       else {
-               entry->proc_fops = &acpi_button_info_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
 
        /* show lid state [R] */
        if (button->type == ACPI_BUTTON_TYPE_LID) {
-               entry = create_proc_entry(ACPI_BUTTON_FILE_STATE,
-                                         S_IRUGO, acpi_device_dir(device));
+               entry = proc_create_data(ACPI_BUTTON_FILE_STATE,
+                                        S_IRUGO, acpi_device_dir(device),
+                                        &acpi_button_state_fops,
+                                        acpi_driver_data(device));
                if (!entry)
                        return -ENODEV;
-               else {
-                       entry->proc_fops = &acpi_button_state_fops;
-                       entry->data = acpi_driver_data(device);
-                       entry->owner = THIS_MODULE;
-               }
        }
 
        return 0;
index 7222a18a03198d0bc70121d1246dc27af1d0629e..e3f04b272f3f23829cac4a555677c495ea290cc5 100644 (file)
@@ -669,16 +669,11 @@ static int acpi_ec_add_fs(struct acpi_device *device)
                        return -ENODEV;
        }
 
-       entry = create_proc_entry(ACPI_EC_FILE_INFO, S_IRUGO,
-                                 acpi_device_dir(device));
+       entry = proc_create_data(ACPI_EC_FILE_INFO, S_IRUGO,
+                                acpi_device_dir(device),
+                                &acpi_ec_info_ops, acpi_driver_data(device));
        if (!entry)
                return -ENODEV;
-       else {
-               entry->proc_fops = &acpi_ec_info_ops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
-
        return 0;
 }
 
index abec1ca94cf4bb4f54a387121c93168c944e7d9e..0c24bd4d65629bb4647fee1958ceeac2dda424ad 100644 (file)
@@ -102,6 +102,7 @@ static unsigned int acpi_system_poll_event(struct file *file, poll_table * wait)
 }
 
 static const struct file_operations acpi_system_event_ops = {
+       .owner = THIS_MODULE,
        .open = acpi_system_open_event,
        .read = acpi_system_read_event,
        .release = acpi_system_close_event,
@@ -294,10 +295,9 @@ static int __init acpi_event_init(void)
 
 #ifdef CONFIG_ACPI_PROC_EVENT
        /* 'event' [R] */
-       entry = create_proc_entry("event", S_IRUSR, acpi_root_dir);
-       if (entry)
-               entry->proc_fops = &acpi_system_event_ops;
-       else
+       entry = proc_create("event", S_IRUSR, acpi_root_dir,
+                           &acpi_system_event_ops);
+       if (!entry)
                return -ENODEV;
 #endif
 
index c8e3cba423ef19d7548b63bfdb041d266454d4e1..194077ab9b85859c5077a9ec26ccf6a94d89be56 100644 (file)
@@ -192,17 +192,13 @@ static int acpi_fan_add_fs(struct acpi_device *device)
        }
 
        /* 'status' [R/W] */
-       entry = create_proc_entry(ACPI_FAN_FILE_STATE,
-                                 S_IFREG | S_IRUGO | S_IWUSR,
-                                 acpi_device_dir(device));
+       entry = proc_create_data(ACPI_FAN_FILE_STATE,
+                                S_IFREG | S_IRUGO | S_IWUSR,
+                                acpi_device_dir(device),
+                                &acpi_fan_state_ops,
+                                device);
        if (!entry)
                return -ENODEV;
-       else {
-               entry->proc_fops = &acpi_fan_state_ops;
-               entry->data = device;
-               entry->owner = THIS_MODULE;
-       }
-
        return 0;
 }
 
index 76bf6d90c700efac7905d6167680915ca50e1498..21fc8bf0d31f953e5bb1310bf5e9e9e65668f8ae 100644 (file)
@@ -93,6 +93,7 @@ struct acpi_power_resource {
 static struct list_head acpi_power_resource_list;
 
 static const struct file_operations acpi_power_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_power_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -543,15 +544,11 @@ static int acpi_power_add_fs(struct acpi_device *device)
        }
 
        /* 'status' [R] */
-       entry = create_proc_entry(ACPI_POWER_FILE_STATUS,
-                                 S_IRUGO, acpi_device_dir(device));
+       entry = proc_create_data(ACPI_POWER_FILE_STATUS,
+                                S_IRUGO, acpi_device_dir(device),
+                                &acpi_power_fops, acpi_driver_data(device));
        if (!entry)
                return -EIO;
-       else {
-               entry->proc_fops = &acpi_power_fops;
-               entry->data = acpi_driver_data(device);
-       }
-
        return 0;
 }
 
index a825b431b64f294df234e05e1244d56d6ce83bf3..5241e3ff50803f6048e5084f6c3135678f7465b2 100644 (file)
@@ -112,6 +112,7 @@ static struct acpi_driver acpi_processor_driver = {
 #define UNINSTALL_NOTIFY_HANDLER       2
 
 static const struct file_operations acpi_processor_info_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_processor_info_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -326,40 +327,30 @@ static int acpi_processor_add_fs(struct acpi_device *device)
        acpi_device_dir(device)->owner = THIS_MODULE;
 
        /* 'info' [R] */
-       entry = create_proc_entry(ACPI_PROCESSOR_FILE_INFO,
-                                 S_IRUGO, acpi_device_dir(device));
+       entry = proc_create_data(ACPI_PROCESSOR_FILE_INFO,
+                                S_IRUGO, acpi_device_dir(device),
+                                &acpi_processor_info_fops,
+                                acpi_driver_data(device));
        if (!entry)
                return -EIO;
-       else {
-               entry->proc_fops = &acpi_processor_info_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
 
        /* 'throttling' [R/W] */
-       entry = create_proc_entry(ACPI_PROCESSOR_FILE_THROTTLING,
-                                 S_IFREG | S_IRUGO | S_IWUSR,
-                                 acpi_device_dir(device));
+       entry = proc_create_data(ACPI_PROCESSOR_FILE_THROTTLING,
+                                S_IFREG | S_IRUGO | S_IWUSR,
+                                acpi_device_dir(device),
+                                &acpi_processor_throttling_fops,
+                                acpi_driver_data(device));
        if (!entry)
                return -EIO;
-       else {
-               entry->proc_fops = &acpi_processor_throttling_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
 
        /* 'limit' [R/W] */
-       entry = create_proc_entry(ACPI_PROCESSOR_FILE_LIMIT,
-                                 S_IFREG | S_IRUGO | S_IWUSR,
-                                 acpi_device_dir(device));
+       entry = proc_create_data(ACPI_PROCESSOR_FILE_LIMIT,
+                                S_IFREG | S_IRUGO | S_IWUSR,
+                                acpi_device_dir(device),
+                                &acpi_processor_limit_fops,
+                                acpi_driver_data(device));
        if (!entry)
                return -EIO;
-       else {
-               entry->proc_fops = &acpi_processor_limit_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
-
        return 0;
 }
 
@@ -612,6 +603,15 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid)
                request_region(pr->throttling.address, 6, "ACPI CPU throttle");
        }
 
+       /*
+        * If ACPI describes a slot number for this CPU, we can use it
+        * ensure we get the right value in the "physical id" field
+        * of /proc/cpuinfo
+        */
+       status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer);
+       if (ACPI_SUCCESS(status))
+               arch_fix_phys_package_id(pr->id, object.integer.value);
+
        return 0;
 }
 
index 0d90ff5fd1172440b724f161b1ad51657511eb3a..789d4947ed31db9929c83c931435b067821b8f59 100644 (file)
@@ -1282,6 +1282,7 @@ static int acpi_processor_power_open_fs(struct inode *inode, struct file *file)
 }
 
 static const struct file_operations acpi_processor_power_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_processor_power_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -1822,16 +1823,12 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
        }
 
        /* 'power' [R] */
-       entry = create_proc_entry(ACPI_PROCESSOR_FILE_POWER,
-                                 S_IRUGO, acpi_device_dir(device));
+       entry = proc_create_data(ACPI_PROCESSOR_FILE_POWER,
+                                S_IRUGO, acpi_device_dir(device),
+                                &acpi_processor_power_fops,
+                                acpi_driver_data(device));
        if (!entry)
                return -EIO;
-       else {
-               entry->proc_fops = &acpi_processor_power_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
-
        return 0;
 }
 
index b477a4be8a698fde564465278cf7c09321f9b00b..d80b2d1441afbadb561cf58abfdb135dd20aeb8e 100644 (file)
@@ -411,6 +411,7 @@ EXPORT_SYMBOL(acpi_processor_notify_smm);
 
 static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file);
 static struct file_operations acpi_processor_perf_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_processor_perf_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -456,7 +457,6 @@ static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file)
 
 static void acpi_cpufreq_add_file(struct acpi_processor *pr)
 {
-       struct proc_dir_entry *entry = NULL;
        struct acpi_device *device = NULL;
 
 
@@ -464,14 +464,9 @@ static void acpi_cpufreq_add_file(struct acpi_processor *pr)
                return;
 
        /* add file 'performance' [R/W] */
-       entry = create_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE,
-                                 S_IFREG | S_IRUGO,
-                                 acpi_device_dir(device));
-       if (entry){
-               entry->proc_fops = &acpi_processor_perf_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
+       proc_create_data(ACPI_PROCESSOR_FILE_PERFORMANCE, S_IFREG | S_IRUGO,
+                        acpi_device_dir(device),
+                        &acpi_processor_perf_fops, acpi_driver_data(device));
        return;
 }
 
index 649ae99b9216d3f3a0f19952729f01d7783ae06f..ef34b18f95ca52e50c5bae79c2436d5b76a4d6fb 100644 (file)
@@ -509,6 +509,7 @@ static ssize_t acpi_processor_write_limit(struct file * file,
 }
 
 struct file_operations acpi_processor_limit_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_processor_limit_open_fs,
        .read = seq_read,
        .write = acpi_processor_write_limit,
index 0bba3a914e865562c51b11703fca695cfd0051a0..bb06738860c4113599ab185435834253d8af4afb 100644 (file)
@@ -1252,6 +1252,7 @@ static ssize_t acpi_processor_write_throttling(struct file *file,
 }
 
 struct file_operations acpi_processor_throttling_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_processor_throttling_open_fs,
        .read = seq_read,
        .write = acpi_processor_write_throttling,
index 585ae3c9c8ea98651e33f46de53876fac237f48d..10a36512647ca6107a76c5982a5f3acaa140b571 100644 (file)
@@ -483,8 +483,6 @@ acpi_sbs_add_fs(struct proc_dir_entry **dir,
                struct file_operations *state_fops,
                struct file_operations *alarm_fops, void *data)
 {
-       struct proc_dir_entry *entry = NULL;
-
        if (!*dir) {
                *dir = proc_mkdir(dir_name, parent_dir);
                if (!*dir) {
@@ -494,34 +492,19 @@ acpi_sbs_add_fs(struct proc_dir_entry **dir,
        }
 
        /* 'info' [R] */
-       if (info_fops) {
-               entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir);
-               if (entry) {
-                       entry->proc_fops = info_fops;
-                       entry->data = data;
-                       entry->owner = THIS_MODULE;
-               }
-       }
+       if (info_fops)
+               proc_create_data(ACPI_SBS_FILE_INFO, S_IRUGO, *dir,
+                                info_fops, data);
 
        /* 'state' [R] */
-       if (state_fops) {
-               entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir);
-               if (entry) {
-                       entry->proc_fops = state_fops;
-                       entry->data = data;
-                       entry->owner = THIS_MODULE;
-               }
-       }
+       if (state_fops)
+               proc_create_data(ACPI_SBS_FILE_STATE, S_IRUGO, *dir,
+                                state_fops, data);
 
        /* 'alarm' [R/W] */
-       if (alarm_fops) {
-               entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir);
-               if (entry) {
-                       entry->proc_fops = alarm_fops;
-                       entry->data = data;
-                       entry->owner = THIS_MODULE;
-               }
-       }
+       if (alarm_fops)
+               proc_create_data(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir,
+                                alarm_fops, data);
        return 0;
 }
 
index f8df5217d477ee525c30f4c1050bf7cc8eb6e35b..8a5fe87105139c5529119bfc69b84d349d2cf1e7 100644 (file)
@@ -440,6 +440,7 @@ acpi_system_wakeup_device_open_fs(struct inode *inode, struct file *file)
 }
 
 static const struct file_operations acpi_system_wakeup_device_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_system_wakeup_device_open_fs,
        .read = seq_read,
        .write = acpi_system_write_wakeup_device,
@@ -449,6 +450,7 @@ static const struct file_operations acpi_system_wakeup_device_fops = {
 
 #ifdef CONFIG_ACPI_PROCFS
 static const struct file_operations acpi_system_sleep_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_system_sleep_open_fs,
        .read = seq_read,
        .write = acpi_system_write_sleep,
@@ -459,6 +461,7 @@ static const struct file_operations acpi_system_sleep_fops = {
 
 #ifdef HAVE_ACPI_LEGACY_ALARM
 static const struct file_operations acpi_system_alarm_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_system_alarm_open_fs,
        .read = seq_read,
        .write = acpi_system_write_alarm,
@@ -477,37 +480,26 @@ static u32 rtc_handler(void *context)
 
 static int __init acpi_sleep_proc_init(void)
 {
-       struct proc_dir_entry *entry = NULL;
-
        if (acpi_disabled)
                return 0;
 
 #ifdef CONFIG_ACPI_PROCFS
        /* 'sleep' [R/W] */
-       entry =
-           create_proc_entry("sleep", S_IFREG | S_IRUGO | S_IWUSR,
-                             acpi_root_dir);
-       if (entry)
-               entry->proc_fops = &acpi_system_sleep_fops;
+       proc_create("sleep", S_IFREG | S_IRUGO | S_IWUSR,
+                   acpi_root_dir, &acpi_system_sleep_fops);
 #endif                         /* CONFIG_ACPI_PROCFS */
 
 #ifdef HAVE_ACPI_LEGACY_ALARM
        /* 'alarm' [R/W] */
-       entry =
-           create_proc_entry("alarm", S_IFREG | S_IRUGO | S_IWUSR,
-                             acpi_root_dir);
-       if (entry)
-               entry->proc_fops = &acpi_system_alarm_fops;
+       proc_create("alarm", S_IFREG | S_IRUGO | S_IWUSR,
+                   acpi_root_dir, &acpi_system_alarm_fops);
 
        acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL);
 #endif                         /* HAVE_ACPI_LEGACY_ALARM */
 
        /* 'wakeup device' [R/W] */
-       entry =
-           create_proc_entry("wakeup", S_IFREG | S_IRUGO | S_IWUSR,
-                             acpi_root_dir);
-       if (entry)
-               entry->proc_fops = &acpi_system_wakeup_device_fops;
+       proc_create("wakeup", S_IFREG | S_IRUGO | S_IWUSR,
+                   acpi_root_dir, &acpi_system_wakeup_device_fops);
 
        return 0;
 }
index 4749f379a915a4c4f6308f21b21de4205f399387..769f24855eb6356b7cfb437e6982d20149f1aca2 100644 (file)
@@ -396,6 +396,7 @@ static int acpi_system_info_open_fs(struct inode *inode, struct file *file)
 }
 
 static const struct file_operations acpi_system_info_ops = {
+       .owner = THIS_MODULE,
        .open = acpi_system_info_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -406,6 +407,7 @@ static ssize_t acpi_system_read_dsdt(struct file *, char __user *, size_t,
                                     loff_t *);
 
 static const struct file_operations acpi_system_dsdt_ops = {
+       .owner = THIS_MODULE,
        .read = acpi_system_read_dsdt,
 };
 
@@ -430,6 +432,7 @@ static ssize_t acpi_system_read_fadt(struct file *, char __user *, size_t,
                                     loff_t *);
 
 static const struct file_operations acpi_system_fadt_ops = {
+       .owner = THIS_MODULE,
        .read = acpi_system_read_fadt,
 };
 
@@ -454,31 +457,23 @@ static int acpi_system_procfs_init(void)
 {
        struct proc_dir_entry *entry;
        int error = 0;
-       char *name;
 
        /* 'info' [R] */
-       name = ACPI_SYSTEM_FILE_INFO;
-       entry = create_proc_entry(name, S_IRUGO, acpi_root_dir);
+       entry = proc_create(ACPI_SYSTEM_FILE_INFO, S_IRUGO, acpi_root_dir,
+                           &acpi_system_info_ops);
        if (!entry)
                goto Error;
-       else {
-               entry->proc_fops = &acpi_system_info_ops;
-       }
 
        /* 'dsdt' [R] */
-       name = ACPI_SYSTEM_FILE_DSDT;
-       entry = create_proc_entry(name, S_IRUSR, acpi_root_dir);
-       if (entry)
-               entry->proc_fops = &acpi_system_dsdt_ops;
-       else
+       entry = proc_create(ACPI_SYSTEM_FILE_DSDT, S_IRUSR, acpi_root_dir,
+                           &acpi_system_dsdt_ops);
+       if (!entry)
                goto Error;
 
        /* 'fadt' [R] */
-       name = ACPI_SYSTEM_FILE_FADT;
-       entry = create_proc_entry(name, S_IRUSR, acpi_root_dir);
-       if (entry)
-               entry->proc_fops = &acpi_system_fadt_ops;
-       else
+       entry = proc_create(ACPI_SYSTEM_FILE_FADT, S_IRUSR, acpi_root_dir,
+                           &acpi_system_fadt_ops);
+       if (!entry)
                goto Error;
 
       Done:
index 766bd25d3376ac35f326c72ae9909777bb839004..0815ac3ae3d6c49a1a46282b0cfaea2418ddca6b 100644 (file)
@@ -198,6 +198,7 @@ struct acpi_thermal {
 };
 
 static const struct file_operations acpi_thermal_state_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_thermal_state_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -205,6 +206,7 @@ static const struct file_operations acpi_thermal_state_fops = {
 };
 
 static const struct file_operations acpi_thermal_temp_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_thermal_temp_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -212,6 +214,7 @@ static const struct file_operations acpi_thermal_temp_fops = {
 };
 
 static const struct file_operations acpi_thermal_trip_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_thermal_trip_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -219,6 +222,7 @@ static const struct file_operations acpi_thermal_trip_fops = {
 };
 
 static const struct file_operations acpi_thermal_cooling_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_thermal_cooling_open_fs,
        .read = seq_read,
        .write = acpi_thermal_write_cooling_mode,
@@ -227,6 +231,7 @@ static const struct file_operations acpi_thermal_cooling_fops = {
 };
 
 static const struct file_operations acpi_thermal_polling_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_thermal_polling_open_fs,
        .read = seq_read,
        .write = acpi_thermal_write_polling,
@@ -1419,63 +1424,47 @@ static int acpi_thermal_add_fs(struct acpi_device *device)
        }
 
        /* 'state' [R] */
-       entry = create_proc_entry(ACPI_THERMAL_FILE_STATE,
-                                 S_IRUGO, acpi_device_dir(device));
+       entry = proc_create_data(ACPI_THERMAL_FILE_STATE,
+                                S_IRUGO, acpi_device_dir(device),
+                                &acpi_thermal_state_fops,
+                                acpi_driver_data(device));
        if (!entry)
                return -ENODEV;
-       else {
-               entry->proc_fops = &acpi_thermal_state_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
 
        /* 'temperature' [R] */
-       entry = create_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE,
-                                 S_IRUGO, acpi_device_dir(device));
+       entry = proc_create_data(ACPI_THERMAL_FILE_TEMPERATURE,
+                                S_IRUGO, acpi_device_dir(device),
+                                &acpi_thermal_temp_fops,
+                                acpi_driver_data(device));
        if (!entry)
                return -ENODEV;
-       else {
-               entry->proc_fops = &acpi_thermal_temp_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
 
        /* 'trip_points' [R] */
-       entry = create_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS,
-                                 S_IRUGO,
-                                 acpi_device_dir(device));
+       entry = proc_create_data(ACPI_THERMAL_FILE_TRIP_POINTS,
+                                S_IRUGO,
+                                acpi_device_dir(device),
+                                &acpi_thermal_trip_fops,
+                                acpi_driver_data(device));
        if (!entry)
                return -ENODEV;
-       else {
-               entry->proc_fops = &acpi_thermal_trip_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
 
        /* 'cooling_mode' [R/W] */
-       entry = create_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE,
-                                 S_IFREG | S_IRUGO | S_IWUSR,
-                                 acpi_device_dir(device));
+       entry = proc_create_data(ACPI_THERMAL_FILE_COOLING_MODE,
+                                S_IFREG | S_IRUGO | S_IWUSR,
+                                acpi_device_dir(device),
+                                &acpi_thermal_cooling_fops,
+                                acpi_driver_data(device));
        if (!entry)
                return -ENODEV;
-       else {
-               entry->proc_fops = &acpi_thermal_cooling_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
 
        /* 'polling_frequency' [R/W] */
-       entry = create_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ,
-                                 S_IFREG | S_IRUGO | S_IWUSR,
-                                 acpi_device_dir(device));
+       entry = proc_create_data(ACPI_THERMAL_FILE_POLLING_FREQ,
+                                S_IFREG | S_IRUGO | S_IWUSR,
+                                acpi_device_dir(device),
+                                &acpi_thermal_polling_fops,
+                                acpi_driver_data(device));
        if (!entry)
                return -ENODEV;
-       else {
-               entry->proc_fops = &acpi_thermal_polling_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
-
        return 0;
 }
 
index 980a74188781eba10b5372934de94bef0e2a2ea2..43b228314a86c656c0f7e189906b8cd4e772a854 100644 (file)
@@ -192,6 +192,7 @@ struct acpi_video_device {
 /* bus */
 static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file);
 static struct file_operations acpi_video_bus_info_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_video_bus_info_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -200,6 +201,7 @@ static struct file_operations acpi_video_bus_info_fops = {
 
 static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file);
 static struct file_operations acpi_video_bus_ROM_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_video_bus_ROM_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -209,6 +211,7 @@ static struct file_operations acpi_video_bus_ROM_fops = {
 static int acpi_video_bus_POST_info_open_fs(struct inode *inode,
                                            struct file *file);
 static struct file_operations acpi_video_bus_POST_info_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_video_bus_POST_info_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -217,6 +220,7 @@ static struct file_operations acpi_video_bus_POST_info_fops = {
 
 static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file);
 static struct file_operations acpi_video_bus_POST_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_video_bus_POST_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -225,6 +229,7 @@ static struct file_operations acpi_video_bus_POST_fops = {
 
 static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file);
 static struct file_operations acpi_video_bus_DOS_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_video_bus_DOS_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -235,6 +240,7 @@ static struct file_operations acpi_video_bus_DOS_fops = {
 static int acpi_video_device_info_open_fs(struct inode *inode,
                                          struct file *file);
 static struct file_operations acpi_video_device_info_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_video_device_info_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -244,6 +250,7 @@ static struct file_operations acpi_video_device_info_fops = {
 static int acpi_video_device_state_open_fs(struct inode *inode,
                                           struct file *file);
 static struct file_operations acpi_video_device_state_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_video_device_state_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -253,6 +260,7 @@ static struct file_operations acpi_video_device_state_fops = {
 static int acpi_video_device_brightness_open_fs(struct inode *inode,
                                                struct file *file);
 static struct file_operations acpi_video_device_brightness_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_video_device_brightness_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -262,6 +270,7 @@ static struct file_operations acpi_video_device_brightness_fops = {
 static int acpi_video_device_EDID_open_fs(struct inode *inode,
                                          struct file *file);
 static struct file_operations acpi_video_device_EDID_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_video_device_EDID_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
@@ -1070,51 +1079,36 @@ static int acpi_video_device_add_fs(struct acpi_device *device)
        }
 
        /* 'info' [R] */
-       entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device));
+       entry = proc_create_data("info", S_IRUGO, acpi_device_dir(device),
+                       &acpi_video_device_info_fops, acpi_driver_data(device));
        if (!entry)
                return -ENODEV;
-       else {
-               entry->proc_fops = &acpi_video_device_info_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
 
        /* 'state' [R/W] */
-       entry =
-           create_proc_entry("state", S_IFREG | S_IRUGO | S_IWUSR,
-                             acpi_device_dir(device));
+       acpi_video_device_state_fops.write = acpi_video_device_write_state;
+       entry = proc_create_data("state", S_IFREG | S_IRUGO | S_IWUSR,
+                                acpi_device_dir(device),
+                                &acpi_video_device_state_fops,
+                                acpi_driver_data(device));
        if (!entry)
                return -ENODEV;
-       else {
-               acpi_video_device_state_fops.write = acpi_video_device_write_state;
-               entry->proc_fops = &acpi_video_device_state_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
 
        /* 'brightness' [R/W] */
-       entry =
-           create_proc_entry("brightness", S_IFREG | S_IRUGO | S_IWUSR,
-                             acpi_device_dir(device));
+       acpi_video_device_brightness_fops.write =
+               acpi_video_device_write_brightness;
+       entry = proc_create_data("brightness", S_IFREG | S_IRUGO | S_IWUSR,
+                                acpi_device_dir(device),
+                                &acpi_video_device_brightness_fops,
+                                acpi_driver_data(device));
        if (!entry)
                return -ENODEV;
-       else {
-               acpi_video_device_brightness_fops.write = acpi_video_device_write_brightness;
-               entry->proc_fops = &acpi_video_device_brightness_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
 
        /* 'EDID' [R] */
-       entry = create_proc_entry("EDID", S_IRUGO, acpi_device_dir(device));
+       entry = proc_create_data("EDID", S_IRUGO, acpi_device_dir(device),
+                                &acpi_video_device_EDID_fops,
+                                acpi_driver_data(device));
        if (!entry)
                return -ENODEV;
-       else {
-               entry->proc_fops = &acpi_video_device_EDID_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
-
        return 0;
 }
 
@@ -1353,61 +1347,43 @@ static int acpi_video_bus_add_fs(struct acpi_device *device)
        }
 
        /* 'info' [R] */
-       entry = create_proc_entry("info", S_IRUGO, acpi_device_dir(device));
+       entry = proc_create_data("info", S_IRUGO, acpi_device_dir(device),
+                                &acpi_video_bus_info_fops,
+                                acpi_driver_data(device));
        if (!entry)
                return -ENODEV;
-       else {
-               entry->proc_fops = &acpi_video_bus_info_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
 
        /* 'ROM' [R] */
-       entry = create_proc_entry("ROM", S_IRUGO, acpi_device_dir(device));
+       entry = proc_create_data("ROM", S_IRUGO, acpi_device_dir(device),
+                                &acpi_video_bus_ROM_fops,
+                                acpi_driver_data(device));
        if (!entry)
                return -ENODEV;
-       else {
-               entry->proc_fops = &acpi_video_bus_ROM_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
 
        /* 'POST_info' [R] */
-       entry =
-           create_proc_entry("POST_info", S_IRUGO, acpi_device_dir(device));
+       entry = proc_create_data("POST_info", S_IRUGO, acpi_device_dir(device),
+                                &acpi_video_bus_POST_info_fops,
+                                acpi_driver_data(device));
        if (!entry)
                return -ENODEV;
-       else {
-               entry->proc_fops = &acpi_video_bus_POST_info_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
 
        /* 'POST' [R/W] */
-       entry =
-           create_proc_entry("POST", S_IFREG | S_IRUGO | S_IRUSR,
-                             acpi_device_dir(device));
+       acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST;
+       entry = proc_create_data("POST", S_IFREG | S_IRUGO | S_IRUSR,
+                                acpi_device_dir(device),
+                                &acpi_video_bus_POST_fops,
+                                acpi_driver_data(device));
        if (!entry)
                return -ENODEV;
-       else {
-               acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST;
-               entry->proc_fops = &acpi_video_bus_POST_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
 
        /* 'DOS' [R/W] */
-       entry =
-           create_proc_entry("DOS", S_IFREG | S_IRUGO | S_IRUSR,
-                             acpi_device_dir(device));
+       acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS;
+       entry = proc_create_data("DOS", S_IFREG | S_IRUGO | S_IRUSR,
+                                acpi_device_dir(device),
+                                &acpi_video_bus_DOS_fops,
+                                acpi_driver_data(device));
        if (!entry)
                return -ENODEV;
-       else {
-               acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS;
-               entry->proc_fops = &acpi_video_bus_DOS_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
 
        return 0;
 }
index 292aa9a0f02f8d5b3913bdc5dca00ab86fda641f..1c11df9a5f32a92e3ff7fda7700450deccf228b4 100644 (file)
@@ -566,11 +566,11 @@ config PATA_RADISYS
 
          If unsure, say N.
 
-config PATA_RB500
-       tristate "RouterBoard 500 PATA CompactFlash support"
-       depends on MIKROTIK_RB500
+config PATA_RB532
+       tristate "RouterBoard 532 PATA CompactFlash support"
+       depends on MIKROTIK_RB532
        help
-         This option enables support for the RouterBoard 500
+         This option enables support for the RouterBoard 532
          PATA CompactFlash controller.
 
          If unsure, say N.
index 1fbc2aa648b739955f1bb746c2ba0703039e4bb7..b693d829383a3b7ff9e33bd0d181523f23297379 100644 (file)
@@ -55,7 +55,7 @@ obj-$(CONFIG_PATA_PDC2027X)   += pata_pdc2027x.o
 obj-$(CONFIG_PATA_PDC_OLD)     += pata_pdc202xx_old.o
 obj-$(CONFIG_PATA_QDI)         += pata_qdi.o
 obj-$(CONFIG_PATA_RADISYS)     += pata_radisys.o
-obj-$(CONFIG_PATA_RB500)       += pata_rb500_cf.o
+obj-$(CONFIG_PATA_RB532)       += pata_rb532_cf.o
 obj-$(CONFIG_PATA_RZ1000)      += pata_rz1000.o
 obj-$(CONFIG_PATA_SC1200)      += pata_sc1200.o
 obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o
index 7c4f886f1f1635cc99911db1085f5630ac9ba77f..8cace9aa9c0398bafe101115ba511bb5dd29f0fb 100644 (file)
@@ -358,7 +358,7 @@ static const struct ata_port_info ahci_port_info[] = {
        /* board_ahci_sb600 */
        {
                AHCI_HFLAGS     (AHCI_HFLAG_IGN_SERR_INTERNAL |
-                                AHCI_HFLAG_32BIT_ONLY |
+                                AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
                                 AHCI_HFLAG_SECT255 | AHCI_HFLAG_NO_PMP),
                .flags          = AHCI_FLAG_COMMON,
                .pio_mask       = 0x1f, /* pio0-4 */
index 51b7d2fad36a2539d72da75f44bcb2683ee041a5..3bc488538204abe225b388346d3b2a65a1c5ed5d 100644 (file)
@@ -3933,6 +3933,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
 
        /* Devices which get the IVB wrong */
        { "QUANTUM FIREBALLlct10 05", "A03.0900", ATA_HORKAGE_IVB, },
+       /* Maybe we should just blacklist TSSTcorp... */
+       { "TSSTcorp CDDVDW SH-S202H", "SB00",     ATA_HORKAGE_IVB, },
+       { "TSSTcorp CDDVDW SH-S202H", "SB01",     ATA_HORKAGE_IVB, },
        { "TSSTcorp CDDVDW SH-S202J", "SB00",     ATA_HORKAGE_IVB, },
        { "TSSTcorp CDDVDW SH-S202J", "SB01",     ATA_HORKAGE_IVB, },
        { "TSSTcorp CDDVDW SH-S202N", "SB00",     ATA_HORKAGE_IVB, },
index a34f32442edf8687c832213f02c3a01e144d49a1..3ce43920e459b037d685239ec1315ed11097df6a 100644 (file)
 
 #include "libata.h"
 
-#define SECTOR_SIZE    512
+#define SECTOR_SIZE            512
+#define ATA_SCSI_RBUF_SIZE     4096
+
+static DEFINE_SPINLOCK(ata_scsi_rbuf_lock);
+static u8 ata_scsi_rbuf[ATA_SCSI_RBUF_SIZE];
 
 typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc);
 
@@ -179,6 +183,13 @@ DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR,
                ata_scsi_lpm_show, ata_scsi_lpm_put);
 EXPORT_SYMBOL_GPL(dev_attr_link_power_management_policy);
 
+static void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
+{
+       cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
+       scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq);
+}
+
 static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
                                   void (*done)(struct scsi_cmnd *))
 {
@@ -1632,53 +1643,48 @@ defer:
 
 /**
  *     ata_scsi_rbuf_get - Map response buffer.
- *     @cmd: SCSI command containing buffer to be mapped.
- *     @buf_out: Pointer to mapped area.
+ *     @flags: unsigned long variable to store irq enable status
+ *     @copy_in: copy in from user buffer
  *
- *     Maps buffer contained within SCSI command @cmd.
+ *     Prepare buffer for simulated SCSI commands.
  *
  *     LOCKING:
- *     spin_lock_irqsave(host lock)
+ *     spin_lock_irqsave(ata_scsi_rbuf_lock) on success
  *
  *     RETURNS:
- *     Length of response buffer.
+ *     Pointer to response buffer.
  */
-
-static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out)
+static void *ata_scsi_rbuf_get(struct scsi_cmnd *cmd, bool copy_in,
+                              unsigned long *flags)
 {
-       u8 *buf;
-       unsigned int buflen;
-
-       struct scatterlist *sg = scsi_sglist(cmd);
+       spin_lock_irqsave(&ata_scsi_rbuf_lock, *flags);
 
-       if (sg) {
-               buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
-               buflen = sg->length;
-       } else {
-               buf = NULL;
-               buflen = 0;
-       }
-
-       *buf_out = buf;
-       return buflen;
+       memset(ata_scsi_rbuf, 0, ATA_SCSI_RBUF_SIZE);
+       if (copy_in)
+               sg_copy_to_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
+                                 ata_scsi_rbuf, ATA_SCSI_RBUF_SIZE);
+       return ata_scsi_rbuf;
 }
 
 /**
  *     ata_scsi_rbuf_put - Unmap response buffer.
  *     @cmd: SCSI command containing buffer to be unmapped.
- *     @buf: buffer to unmap
+ *     @copy_out: copy out result
+ *     @flags: @flags passed to ata_scsi_rbuf_get()
  *
- *     Unmaps response buffer contained within @cmd.
+ *     Returns rbuf buffer.  The result is copied to @cmd's buffer if
+ *     @copy_back is true.
  *
  *     LOCKING:
- *     spin_lock_irqsave(host lock)
+ *     Unlocks ata_scsi_rbuf_lock.
  */
-
-static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
+static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, bool copy_out,
+                                    unsigned long *flags)
 {
-       struct scatterlist *sg = scsi_sglist(cmd);
-       if (sg)
-               kunmap_atomic(buf - sg->offset, KM_IRQ0);
+       if (copy_out)
+               sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
+                                   ata_scsi_rbuf, ATA_SCSI_RBUF_SIZE);
+       spin_unlock_irqrestore(&ata_scsi_rbuf_lock, *flags);
 }
 
 /**
@@ -1696,51 +1702,27 @@ static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
  *     LOCKING:
  *     spin_lock_irqsave(host lock)
  */
-
-void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
-                       unsigned int (*actor) (struct ata_scsi_args *args,
-                                              u8 *rbuf, unsigned int buflen))
+static void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
+               unsigned int (*actor)(struct ata_scsi_args *args, u8 *rbuf))
 {
        u8 *rbuf;
-       unsigned int buflen, rc;
+       unsigned int rc;
        struct scsi_cmnd *cmd = args->cmd;
        unsigned long flags;
 
-       local_irq_save(flags);
-
-       buflen = ata_scsi_rbuf_get(cmd, &rbuf);
-       memset(rbuf, 0, buflen);
-       rc = actor(args, rbuf, buflen);
-       ata_scsi_rbuf_put(cmd, rbuf);
-
-       local_irq_restore(flags);
+       rbuf = ata_scsi_rbuf_get(cmd, false, &flags);
+       rc = actor(args, rbuf);
+       ata_scsi_rbuf_put(cmd, rc == 0, &flags);
 
        if (rc == 0)
                cmd->result = SAM_STAT_GOOD;
        args->done(cmd);
 }
 
-/**
- *     ATA_SCSI_RBUF_SET - helper to set values in SCSI response buffer
- *     @idx: byte index into SCSI response buffer
- *     @val: value to set
- *
- *     To be used by SCSI command simulator functions.  This macros
- *     expects two local variables, u8 *rbuf and unsigned int buflen,
- *     are in scope.
- *
- *     LOCKING:
- *     None.
- */
-#define ATA_SCSI_RBUF_SET(idx, val) do { \
-               if ((idx) < buflen) rbuf[(idx)] = (u8)(val); \
-       } while (0)
-
 /**
  *     ata_scsiop_inq_std - Simulate INQUIRY command
  *     @args: device IDENTIFY data / SCSI command of interest.
  *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- *     @buflen: Response buffer length.
  *
  *     Returns standard device identification data associated
  *     with non-VPD INQUIRY command output.
@@ -1748,10 +1730,17 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
  *     LOCKING:
  *     spin_lock_irqsave(host lock)
  */
-
-unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
-                              unsigned int buflen)
+static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
 {
+       const u8 versions[] = {
+               0x60,   /* SAM-3 (no version claimed) */
+
+               0x03,
+               0x20,   /* SBC-2 (no version claimed) */
+
+               0x02,
+               0x60    /* SPC-3 (no version claimed) */
+       };
        u8 hdr[] = {
                TYPE_DISK,
                0,
@@ -1760,35 +1749,21 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
                95 - 4
        };
 
+       VPRINTK("ENTER\n");
+
        /* set scsi removeable (RMB) bit per ata bit */
        if (ata_id_removeable(args->id))
                hdr[1] |= (1 << 7);
 
-       VPRINTK("ENTER\n");
-
        memcpy(rbuf, hdr, sizeof(hdr));
+       memcpy(&rbuf[8], "ATA     ", 8);
+       ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16);
+       ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
 
-       if (buflen > 35) {
-               memcpy(&rbuf[8], "ATA     ", 8);
-               ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16);
-               ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
-               if (rbuf[32] == 0 || rbuf[32] == ' ')
-                       memcpy(&rbuf[32], "n/a ", 4);
-       }
-
-       if (buflen > 63) {
-               const u8 versions[] = {
-                       0x60,   /* SAM-3 (no version claimed) */
-
-                       0x03,
-                       0x20,   /* SBC-2 (no version claimed) */
+       if (rbuf[32] == 0 || rbuf[32] == ' ')
+               memcpy(&rbuf[32], "n/a ", 4);
 
-                       0x02,
-                       0x60    /* SPC-3 (no version claimed) */
-               };
-
-               memcpy(rbuf + 59, versions, sizeof(versions));
-       }
+       memcpy(rbuf + 59, versions, sizeof(versions));
 
        return 0;
 }
@@ -1797,27 +1772,22 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
  *     ata_scsiop_inq_00 - Simulate INQUIRY VPD page 0, list of pages
  *     @args: device IDENTIFY data / SCSI command of interest.
  *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- *     @buflen: Response buffer length.
  *
  *     Returns list of inquiry VPD pages available.
  *
  *     LOCKING:
  *     spin_lock_irqsave(host lock)
  */
-
-unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
-                             unsigned int buflen)
+static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf)
 {
        const u8 pages[] = {
                0x00,   /* page 0x00, this page */
                0x80,   /* page 0x80, unit serial no page */
                0x83    /* page 0x83, device ident page */
        };
-       rbuf[3] = sizeof(pages);        /* number of supported VPD pages */
-
-       if (buflen > 6)
-               memcpy(rbuf + 4, pages, sizeof(pages));
 
+       rbuf[3] = sizeof(pages);        /* number of supported VPD pages */
+       memcpy(rbuf + 4, pages, sizeof(pages));
        return 0;
 }
 
@@ -1825,16 +1795,13 @@ unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
  *     ata_scsiop_inq_80 - Simulate INQUIRY VPD page 80, device serial number
  *     @args: device IDENTIFY data / SCSI command of interest.
  *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- *     @buflen: Response buffer length.
  *
  *     Returns ATA device serial number.
  *
  *     LOCKING:
  *     spin_lock_irqsave(host lock)
  */
-
-unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
-                             unsigned int buflen)
+static unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf)
 {
        const u8 hdr[] = {
                0,
@@ -1842,12 +1809,10 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
                0,
                ATA_ID_SERNO_LEN,       /* page len */
        };
-       memcpy(rbuf, hdr, sizeof(hdr));
-
-       if (buflen > (ATA_ID_SERNO_LEN + 4 - 1))
-               ata_id_string(args->id, (unsigned char *) &rbuf[4],
-                             ATA_ID_SERNO, ATA_ID_SERNO_LEN);
 
+       memcpy(rbuf, hdr, sizeof(hdr));
+       ata_id_string(args->id, (unsigned char *) &rbuf[4],
+                     ATA_ID_SERNO, ATA_ID_SERNO_LEN);
        return 0;
 }
 
@@ -1855,7 +1820,6 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
  *     ata_scsiop_inq_83 - Simulate INQUIRY VPD page 83, device identity
  *     @args: device IDENTIFY data / SCSI command of interest.
  *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- *     @buflen: Response buffer length.
  *
  *     Yields two logical unit device identification designators:
  *      - vendor specific ASCII containing the ATA serial number
@@ -1865,41 +1829,37 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
  *     LOCKING:
  *     spin_lock_irqsave(host lock)
  */
-
-unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
-                             unsigned int buflen)
+static unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf)
 {
-       int num;
        const int sat_model_serial_desc_len = 68;
+       int num;
 
        rbuf[1] = 0x83;                 /* this page code */
        num = 4;
 
-       if (buflen > (ATA_ID_SERNO_LEN + num + 3)) {
-               /* piv=0, assoc=lu, code_set=ACSII, designator=vendor */
-               rbuf[num + 0] = 2;
-               rbuf[num + 3] = ATA_ID_SERNO_LEN;
-               num += 4;
-               ata_id_string(args->id, (unsigned char *) rbuf + num,
-                             ATA_ID_SERNO, ATA_ID_SERNO_LEN);
-               num += ATA_ID_SERNO_LEN;
-       }
-       if (buflen > (sat_model_serial_desc_len + num + 3)) {
-               /* SAT defined lu model and serial numbers descriptor */
-               /* piv=0, assoc=lu, code_set=ACSII, designator=t10 vendor id */
-               rbuf[num + 0] = 2;
-               rbuf[num + 1] = 1;
-               rbuf[num + 3] = sat_model_serial_desc_len;
-               num += 4;
-               memcpy(rbuf + num, "ATA     ", 8);
-               num += 8;
-               ata_id_string(args->id, (unsigned char *) rbuf + num,
-                             ATA_ID_PROD, ATA_ID_PROD_LEN);
-               num += ATA_ID_PROD_LEN;
-               ata_id_string(args->id, (unsigned char *) rbuf + num,
-                             ATA_ID_SERNO, ATA_ID_SERNO_LEN);
-               num += ATA_ID_SERNO_LEN;
-       }
+       /* piv=0, assoc=lu, code_set=ACSII, designator=vendor */
+       rbuf[num + 0] = 2;
+       rbuf[num + 3] = ATA_ID_SERNO_LEN;
+       num += 4;
+       ata_id_string(args->id, (unsigned char *) rbuf + num,
+                     ATA_ID_SERNO, ATA_ID_SERNO_LEN);
+       num += ATA_ID_SERNO_LEN;
+
+       /* SAT defined lu model and serial numbers descriptor */
+       /* piv=0, assoc=lu, code_set=ACSII, designator=t10 vendor id */
+       rbuf[num + 0] = 2;
+       rbuf[num + 1] = 1;
+       rbuf[num + 3] = sat_model_serial_desc_len;
+       num += 4;
+       memcpy(rbuf + num, "ATA     ", 8);
+       num += 8;
+       ata_id_string(args->id, (unsigned char *) rbuf + num, ATA_ID_PROD,
+                     ATA_ID_PROD_LEN);
+       num += ATA_ID_PROD_LEN;
+       ata_id_string(args->id, (unsigned char *) rbuf + num, ATA_ID_SERNO,
+                     ATA_ID_SERNO_LEN);
+       num += ATA_ID_SERNO_LEN;
+
        rbuf[3] = num - 4;    /* page len (assume less than 256 bytes) */
        return 0;
 }
@@ -1908,35 +1868,26 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
  *     ata_scsiop_inq_89 - Simulate INQUIRY VPD page 89, ATA info
  *     @args: device IDENTIFY data / SCSI command of interest.
  *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- *     @buflen: Response buffer length.
  *
  *     Yields SAT-specified ATA VPD page.
  *
  *     LOCKING:
  *     spin_lock_irqsave(host lock)
  */
-
-static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
-                             unsigned int buflen)
+static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf)
 {
-       u8 pbuf[60];
        struct ata_taskfile tf;
-       unsigned int i;
 
-       if (!buflen)
-               return 0;
-
-       memset(&pbuf, 0, sizeof(pbuf));
        memset(&tf, 0, sizeof(tf));
 
-       pbuf[1] = 0x89;                 /* our page code */
-       pbuf[2] = (0x238 >> 8);         /* page size fixed at 238h */
-       pbuf[3] = (0x238 & 0xff);
+       rbuf[1] = 0x89;                 /* our page code */
+       rbuf[2] = (0x238 >> 8);         /* page size fixed at 238h */
+       rbuf[3] = (0x238 & 0xff);
 
-       memcpy(&pbuf[8], "linux   ", 8);
-       memcpy(&pbuf[16], "libata          ", 16);
-       memcpy(&pbuf[32], DRV_VERSION, 4);
-       ata_id_string(args->id, &pbuf[32], ATA_ID_FW_REV, 4);
+       memcpy(&rbuf[8], "linux   ", 8);
+       memcpy(&rbuf[16], "libata          ", 16);
+       memcpy(&rbuf[32], DRV_VERSION, 4);
+       ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
 
        /* we don't store the ATA device signature, so we fake it */
 
@@ -1944,19 +1895,12 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
        tf.lbal = 0x1;
        tf.nsect = 0x1;
 
-       ata_tf_to_fis(&tf, 0, 1, &pbuf[36]);    /* TODO: PMP? */
-       pbuf[36] = 0x34;                /* force D2H Reg FIS (34h) */
+       ata_tf_to_fis(&tf, 0, 1, &rbuf[36]);    /* TODO: PMP? */
+       rbuf[36] = 0x34;                /* force D2H Reg FIS (34h) */
 
-       pbuf[56] = ATA_CMD_ID_ATA;
+       rbuf[56] = ATA_CMD_ID_ATA;
 
-       i = min(buflen, 60U);
-       memcpy(rbuf, &pbuf[0], i);
-       buflen -= i;
-
-       if (!buflen)
-               return 0;
-
-       memcpy(&rbuf[60], &args->id[0], min(buflen, 512U));
+       memcpy(&rbuf[60], &args->id[0], 512);
        return 0;
 }
 
@@ -1964,7 +1908,6 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
  *     ata_scsiop_noop - Command handler that simply returns success.
  *     @args: device IDENTIFY data / SCSI command of interest.
  *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- *     @buflen: Response buffer length.
  *
  *     No operation.  Simply returns success to caller, to indicate
  *     that the caller should successfully complete this SCSI command.
@@ -1972,47 +1915,16 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
  *     LOCKING:
  *     spin_lock_irqsave(host lock)
  */
-
-unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf,
-                           unsigned int buflen)
+static unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf)
 {
        VPRINTK("ENTER\n");
        return 0;
 }
 
-/**
- *     ata_msense_push - Push data onto MODE SENSE data output buffer
- *     @ptr_io: (input/output) Location to store more output data
- *     @last: End of output data buffer
- *     @buf: Pointer to BLOB being added to output buffer
- *     @buflen: Length of BLOB
- *
- *     Store MODE SENSE data on an output buffer.
- *
- *     LOCKING:
- *     None.
- */
-
-static void ata_msense_push(u8 **ptr_io, const u8 *last,
-                           const u8 *buf, unsigned int buflen)
-{
-       u8 *ptr = *ptr_io;
-
-       if ((ptr + buflen - 1) > last)
-               return;
-
-       memcpy(ptr, buf, buflen);
-
-       ptr += buflen;
-
-       *ptr_io = ptr;
-}
-
 /**
  *     ata_msense_caching - Simulate MODE SENSE caching info page
  *     @id: device IDENTIFY data
- *     @ptr_io: (input/output) Location to store more output data
- *     @last: End of output data buffer
+ *     @buf: output buffer
  *
  *     Generate a caching info page, which conditionally indicates
  *     write caching to the SCSI layer, depending on device
@@ -2021,58 +1933,43 @@ static void ata_msense_push(u8 **ptr_io, const u8 *last,
  *     LOCKING:
  *     None.
  */
-
-static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io,
-                                      const u8 *last)
+static unsigned int ata_msense_caching(u16 *id, u8 *buf)
 {
-       u8 page[CACHE_MPAGE_LEN];
-
-       memcpy(page, def_cache_mpage, sizeof(page));
+       memcpy(buf, def_cache_mpage, sizeof(def_cache_mpage));
        if (ata_id_wcache_enabled(id))
-               page[2] |= (1 << 2);    /* write cache enable */
+               buf[2] |= (1 << 2);     /* write cache enable */
        if (!ata_id_rahead_enabled(id))
-               page[12] |= (1 << 5);   /* disable read ahead */
-
-       ata_msense_push(ptr_io, last, page, sizeof(page));
-       return sizeof(page);
+               buf[12] |= (1 << 5);    /* disable read ahead */
+       return sizeof(def_cache_mpage);
 }
 
 /**
  *     ata_msense_ctl_mode - Simulate MODE SENSE control mode page
- *     @dev: Device associated with this MODE SENSE command
- *     @ptr_io: (input/output) Location to store more output data
- *     @last: End of output data buffer
+ *     @buf: output buffer
  *
  *     Generate a generic MODE SENSE control mode page.
  *
  *     LOCKING:
  *     None.
  */
-
-static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last)
+static unsigned int ata_msense_ctl_mode(u8 *buf)
 {
-       ata_msense_push(ptr_io, last, def_control_mpage,
-                       sizeof(def_control_mpage));
+       memcpy(buf, def_control_mpage, sizeof(def_control_mpage));
        return sizeof(def_control_mpage);
 }
 
 /**
  *     ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page
- *     @dev: Device associated with this MODE SENSE command
- *     @ptr_io: (input/output) Location to store more output data
- *     @last: End of output data buffer
+ *     @bufp: output buffer
  *
  *     Generate a generic MODE SENSE r/w error recovery page.
  *
  *     LOCKING:
  *     None.
  */
-
-static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
+static unsigned int ata_msense_rw_recovery(u8 *buf)
 {
-
-       ata_msense_push(ptr_io, last, def_rw_recovery_mpage,
-                       sizeof(def_rw_recovery_mpage));
+       memcpy(buf, def_rw_recovery_mpage, sizeof(def_rw_recovery_mpage));
        return sizeof(def_rw_recovery_mpage);
 }
 
@@ -2104,7 +2001,6 @@ static int ata_dev_supports_fua(u16 *id)
  *     ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands
  *     @args: device IDENTIFY data / SCSI command of interest.
  *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- *     @buflen: Response buffer length.
  *
  *     Simulate MODE SENSE commands. Assume this is invoked for direct
  *     access devices (e.g. disks) only. There should be no block
@@ -2113,19 +2009,17 @@ static int ata_dev_supports_fua(u16 *id)
  *     LOCKING:
  *     spin_lock_irqsave(host lock)
  */
-
-unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
-                                 unsigned int buflen)
+static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
 {
        struct ata_device *dev = args->dev;
-       u8 *scsicmd = args->cmd->cmnd, *p, *last;
+       u8 *scsicmd = args->cmd->cmnd, *p = rbuf;
        const u8 sat_blk_desc[] = {
                0, 0, 0, 0,     /* number of blocks: sat unspecified */
                0,
                0, 0x2, 0x0     /* block length: 512 bytes */
        };
        u8 pg, spg;
-       unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen;
+       unsigned int ebd, page_control, six_byte;
        u8 dpofua;
 
        VPRINTK("ENTER\n");
@@ -2148,17 +2042,10 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
                goto invalid_fld;
        }
 
-       if (six_byte) {
-               output_len = 4 + (ebd ? 8 : 0);
-               alloc_len = scsicmd[4];
-       } else {
-               output_len = 8 + (ebd ? 8 : 0);
-               alloc_len = (scsicmd[7] << 8) + scsicmd[8];
-       }
-       minlen = (alloc_len < buflen) ? alloc_len : buflen;
-
-       p = rbuf + output_len;
-       last = rbuf + minlen - 1;
+       if (six_byte)
+               p += 4 + (ebd ? 8 : 0);
+       else
+               p += 8 + (ebd ? 8 : 0);
 
        pg = scsicmd[2] & 0x3f;
        spg = scsicmd[3];
@@ -2171,61 +2058,48 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
 
        switch(pg) {
        case RW_RECOVERY_MPAGE:
-               output_len += ata_msense_rw_recovery(&p, last);
+               p += ata_msense_rw_recovery(p);
                break;
 
        case CACHE_MPAGE:
-               output_len += ata_msense_caching(args->id, &p, last);
+               p += ata_msense_caching(args->id, p);
                break;
 
-       case CONTROL_MPAGE: {
-               output_len += ata_msense_ctl_mode(&p, last);
+       case CONTROL_MPAGE:
+               p += ata_msense_ctl_mode(p);
                break;
-               }
 
        case ALL_MPAGES:
-               output_len += ata_msense_rw_recovery(&p, last);
-               output_len += ata_msense_caching(args->id, &p, last);
-               output_len += ata_msense_ctl_mode(&p, last);
+               p += ata_msense_rw_recovery(p);
+               p += ata_msense_caching(args->id, p);
+               p += ata_msense_ctl_mode(p);
                break;
 
        default:                /* invalid page code */
                goto invalid_fld;
        }
 
-       if (minlen < 1)
-               return 0;
-
        dpofua = 0;
        if (ata_dev_supports_fua(args->id) && (dev->flags & ATA_DFLAG_LBA48) &&
            (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count))
                dpofua = 1 << 4;
 
        if (six_byte) {
-               output_len--;
-               rbuf[0] = output_len;
-               if (minlen > 2)
-                       rbuf[2] |= dpofua;
+               rbuf[0] = p - rbuf - 1;
+               rbuf[2] |= dpofua;
                if (ebd) {
-                       if (minlen > 3)
-                               rbuf[3] = sizeof(sat_blk_desc);
-                       if (minlen > 11)
-                               memcpy(rbuf + 4, sat_blk_desc,
-                                      sizeof(sat_blk_desc));
+                       rbuf[3] = sizeof(sat_blk_desc);
+                       memcpy(rbuf + 4, sat_blk_desc, sizeof(sat_blk_desc));
                }
        } else {
-               output_len -= 2;
+               unsigned int output_len = p - rbuf - 2;
+
                rbuf[0] = output_len >> 8;
-               if (minlen > 1)
-                       rbuf[1] = output_len;
-               if (minlen > 3)
-                       rbuf[3] |= dpofua;
+               rbuf[1] = output_len;
+               rbuf[3] |= dpofua;
                if (ebd) {
-                       if (minlen > 7)
-                               rbuf[7] = sizeof(sat_blk_desc);
-                       if (minlen > 15)
-                               memcpy(rbuf + 8, sat_blk_desc,
-                                      sizeof(sat_blk_desc));
+                       rbuf[7] = sizeof(sat_blk_desc);
+                       memcpy(rbuf + 8, sat_blk_desc, sizeof(sat_blk_desc));
                }
        }
        return 0;
@@ -2245,15 +2119,13 @@ saving_not_supp:
  *     ata_scsiop_read_cap - Simulate READ CAPACITY[ 16] commands
  *     @args: device IDENTIFY data / SCSI command of interest.
  *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- *     @buflen: Response buffer length.
  *
  *     Simulate READ CAPACITY commands.
  *
  *     LOCKING:
  *     None.
  */
-unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
-                                unsigned int buflen)
+static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
 {
        u64 last_lba = args->dev->n_sectors - 1; /* LBA of the last block */
 
@@ -2264,28 +2136,28 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
                        last_lba = 0xffffffff;
 
                /* sector count, 32-bit */
-               ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 3));
-               ATA_SCSI_RBUF_SET(1, last_lba >> (8 * 2));
-               ATA_SCSI_RBUF_SET(2, last_lba >> (8 * 1));
-               ATA_SCSI_RBUF_SET(3, last_lba);
+               rbuf[0] = last_lba >> (8 * 3);
+               rbuf[1] = last_lba >> (8 * 2);
+               rbuf[2] = last_lba >> (8 * 1);
+               rbuf[3] = last_lba;
 
                /* sector size */
-               ATA_SCSI_RBUF_SET(6, ATA_SECT_SIZE >> 8);
-               ATA_SCSI_RBUF_SET(7, ATA_SECT_SIZE & 0xff);
+               rbuf[6] = ATA_SECT_SIZE >> 8;
+               rbuf[7] = ATA_SECT_SIZE & 0xff;
        } else {
                /* sector count, 64-bit */
-               ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 7));
-               ATA_SCSI_RBUF_SET(1, last_lba >> (8 * 6));
-               ATA_SCSI_RBUF_SET(2, last_lba >> (8 * 5));
-               ATA_SCSI_RBUF_SET(3, last_lba >> (8 * 4));
-               ATA_SCSI_RBUF_SET(4, last_lba >> (8 * 3));
-               ATA_SCSI_RBUF_SET(5, last_lba >> (8 * 2));
-               ATA_SCSI_RBUF_SET(6, last_lba >> (8 * 1));
-               ATA_SCSI_RBUF_SET(7, last_lba);
+               rbuf[0] = last_lba >> (8 * 7);
+               rbuf[1] = last_lba >> (8 * 6);
+               rbuf[2] = last_lba >> (8 * 5);
+               rbuf[3] = last_lba >> (8 * 4);
+               rbuf[4] = last_lba >> (8 * 3);
+               rbuf[5] = last_lba >> (8 * 2);
+               rbuf[6] = last_lba >> (8 * 1);
+               rbuf[7] = last_lba;
 
                /* sector size */
-               ATA_SCSI_RBUF_SET(10, ATA_SECT_SIZE >> 8);
-               ATA_SCSI_RBUF_SET(11, ATA_SECT_SIZE & 0xff);
+               rbuf[10] = ATA_SECT_SIZE >> 8;
+               rbuf[11] = ATA_SECT_SIZE & 0xff;
        }
 
        return 0;
@@ -2295,16 +2167,13 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
  *     ata_scsiop_report_luns - Simulate REPORT LUNS command
  *     @args: device IDENTIFY data / SCSI command of interest.
  *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
- *     @buflen: Response buffer length.
  *
  *     Simulate REPORT LUNS command.
  *
  *     LOCKING:
  *     spin_lock_irqsave(host lock)
  */
-
-unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
-                                  unsigned int buflen)
+static unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf)
 {
        VPRINTK("ENTER\n");
        rbuf[3] = 8;    /* just one lun, LUN 0, size 8 bytes */
@@ -2312,53 +2181,6 @@ unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
        return 0;
 }
 
-/**
- *     ata_scsi_set_sense - Set SCSI sense data and status
- *     @cmd: SCSI request to be handled
- *     @sk: SCSI-defined sense key
- *     @asc: SCSI-defined additional sense code
- *     @ascq: SCSI-defined additional sense code qualifier
- *
- *     Helper function that builds a valid fixed format, current
- *     response code and the given sense key (sk), additional sense
- *     code (asc) and additional sense code qualifier (ascq) with
- *     a SCSI command status of %SAM_STAT_CHECK_CONDITION and
- *     DRIVER_SENSE set in the upper bits of scsi_cmnd::result .
- *
- *     LOCKING:
- *     Not required
- */
-
-void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
-{
-       cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
-
-       scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq);
-}
-
-/**
- *     ata_scsi_badcmd - End a SCSI request with an error
- *     @cmd: SCSI request to be handled
- *     @done: SCSI command completion function
- *     @asc: SCSI-defined additional sense code
- *     @ascq: SCSI-defined additional sense code qualifier
- *
- *     Helper function that completes a SCSI command with
- *     %SAM_STAT_CHECK_CONDITION, with a sense key %ILLEGAL_REQUEST
- *     and the specified additional sense codes.
- *
- *     LOCKING:
- *     spin_lock_irqsave(host lock)
- */
-
-void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 asc, u8 ascq)
-{
-       DPRINTK("ENTER\n");
-       ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, asc, ascq);
-
-       done(cmd);
-}
-
 static void atapi_sense_complete(struct ata_queued_cmd *qc)
 {
        if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) {
@@ -2485,13 +2307,10 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
                u8 *scsicmd = cmd->cmnd;
 
                if ((scsicmd[0] == INQUIRY) && ((scsicmd[1] & 0x03) == 0)) {
-                       u8 *buf = NULL;
-                       unsigned int buflen;
                        unsigned long flags;
+                       u8 *buf;
 
-                       local_irq_save(flags);
-
-                       buflen = ata_scsi_rbuf_get(cmd, &buf);
+                       buf = ata_scsi_rbuf_get(cmd, true, &flags);
 
        /* ATAPI devices typically report zero for their SCSI version,
         * and sometimes deviate from the spec WRT response data
@@ -2506,9 +2325,7 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
                                buf[3] = 0x32;
                        }
 
-                       ata_scsi_rbuf_put(cmd, buf);
-
-                       local_irq_restore(flags);
+                       ata_scsi_rbuf_put(cmd, true, &flags);
                }
 
                cmd->result = SAM_STAT_GOOD;
index ae2cfd95d43ef7591b1b6ead5b4497080ec5876e..4514283937ea4a9a4254664ac897586266809771 100644 (file)
@@ -146,34 +146,6 @@ extern void ata_scsi_scan_host(struct ata_port *ap, int sync);
 extern int ata_scsi_offline_dev(struct ata_device *dev);
 extern void ata_scsi_media_change_notify(struct ata_device *dev);
 extern void ata_scsi_hotplug(struct work_struct *work);
-extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
-                              unsigned int buflen);
-
-extern unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
-                             unsigned int buflen);
-
-extern unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
-                             unsigned int buflen);
-extern unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
-                             unsigned int buflen);
-extern unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf,
-                           unsigned int buflen);
-extern unsigned int ata_scsiop_sync_cache(struct ata_scsi_args *args, u8 *rbuf,
-                                 unsigned int buflen);
-extern unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
-                                 unsigned int buflen);
-extern unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
-                               unsigned int buflen);
-extern unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
-                                  unsigned int buflen);
-extern void ata_scsi_badcmd(struct scsi_cmnd *cmd,
-                           void (*done)(struct scsi_cmnd *),
-                           u8 asc, u8 ascq);
-extern void ata_scsi_set_sense(struct scsi_cmnd *cmd,
-                              u8 sk, u8 asc, u8 ascq);
-extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
-                        unsigned int (*actor) (struct ata_scsi_args *args,
-                                           u8 *rbuf, unsigned int buflen));
 extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
 extern void ata_scsi_dev_rescan(struct work_struct *work);
 extern int ata_bus_probe(struct ata_port *ap);
index 78738fb4223b666078fc5ac1e0344b13d937d2d7..d7de7baf58a8ccb8551a8685167410b60ddf031d 100644 (file)
@@ -88,8 +88,8 @@ static void atiixp_set_pio_timing(struct ata_port *ap, struct ata_device *adev,
        pci_write_config_word(pdev, ATIIXP_IDE_PIO_MODE, pio_mode_data);
 
        pci_read_config_word(pdev, ATIIXP_IDE_PIO_TIMING, &pio_timing_data);
-       pio_mode_data &= ~(0xFF << timing_shift);
-       pio_mode_data |= (pio_timings[pio] << timing_shift);
+       pio_timing_data &= ~(0xFF << timing_shift);
+       pio_timing_data |= (pio_timings[pio] << timing_shift);
        pci_write_config_word(pdev, ATIIXP_IDE_PIO_TIMING, pio_timing_data);
 }
 
index a75de0684c15cff77f21728fd36af031e7867b2c..9ab89732cf9474f1fa34458717bb9bd7da755d88 100644 (file)
@@ -1272,8 +1272,8 @@ static void bfin_freeze(struct ata_port *ap)
 
 void bfin_thaw(struct ata_port *ap)
 {
+       dev_dbg(ap->dev, "in atapi dma thaw\n");
        bfin_check_status(ap);
-       bfin_irq_clear(ap);
        bfin_irq_on(ap);
 }
 
@@ -1339,13 +1339,130 @@ static int bfin_port_start(struct ata_port *ap)
        return 0;
 }
 
+static unsigned int bfin_ata_host_intr(struct ata_port *ap,
+                                  struct ata_queued_cmd *qc)
+{
+       struct ata_eh_info *ehi = &ap->link.eh_info;
+       u8 status, host_stat = 0;
+
+       VPRINTK("ata%u: protocol %d task_state %d\n",
+               ap->print_id, qc->tf.protocol, ap->hsm_task_state);
+
+       /* Check whether we are expecting interrupt in this state */
+       switch (ap->hsm_task_state) {
+       case HSM_ST_FIRST:
+               /* Some pre-ATAPI-4 devices assert INTRQ
+                * at this state when ready to receive CDB.
+                */
+
+               /* Check the ATA_DFLAG_CDB_INTR flag is enough here.
+                * The flag was turned on only for atapi devices.
+                * No need to check is_atapi_taskfile(&qc->tf) again.
+                */
+               if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+                       goto idle_irq;
+               break;
+       case HSM_ST_LAST:
+               if (qc->tf.protocol == ATA_PROT_DMA ||
+                   qc->tf.protocol == ATAPI_PROT_DMA) {
+                       /* check status of DMA engine */
+                       host_stat = ap->ops->bmdma_status(ap);
+                       VPRINTK("ata%u: host_stat 0x%X\n",
+                               ap->print_id, host_stat);
+
+                       /* if it's not our irq... */
+                       if (!(host_stat & ATA_DMA_INTR))
+                               goto idle_irq;
+
+                       /* before we do anything else, clear DMA-Start bit */
+                       ap->ops->bmdma_stop(qc);
+
+                       if (unlikely(host_stat & ATA_DMA_ERR)) {
+                               /* error when transfering data to/from memory */
+                               qc->err_mask |= AC_ERR_HOST_BUS;
+                               ap->hsm_task_state = HSM_ST_ERR;
+                       }
+               }
+               break;
+       case HSM_ST:
+               break;
+       default:
+               goto idle_irq;
+       }
+
+       /* check altstatus */
+       status = ap->ops->sff_check_altstatus(ap);
+       if (status & ATA_BUSY)
+               goto busy_ata;
+
+       /* check main status, clearing INTRQ */
+       status = ap->ops->sff_check_status(ap);
+       if (unlikely(status & ATA_BUSY))
+               goto busy_ata;
+
+       /* ack bmdma irq events */
+       ap->ops->sff_irq_clear(ap);
+
+       ata_sff_hsm_move(ap, qc, status, 0);
+
+       if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
+                                      qc->tf.protocol == ATAPI_PROT_DMA))
+               ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
+
+busy_ata:
+       return 1;       /* irq handled */
+
+idle_irq:
+       ap->stats.idle_irq++;
+
+#ifdef ATA_IRQ_TRAP
+       if ((ap->stats.idle_irq % 1000) == 0) {
+               ap->ops->irq_ack(ap, 0); /* debug trap */
+               ata_port_printk(ap, KERN_WARNING, "irq trap\n");
+               return 1;
+       }
+#endif
+       return 0;       /* irq not handled */
+}
+
+static irqreturn_t bfin_ata_interrupt(int irq, void *dev_instance)
+{
+       struct ata_host *host = dev_instance;
+       unsigned int i;
+       unsigned int handled = 0;
+       unsigned long flags;
+
+       /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */
+       spin_lock_irqsave(&host->lock, flags);
+
+       for (i = 0; i < host->n_ports; i++) {
+               struct ata_port *ap;
+
+               ap = host->ports[i];
+               if (ap &&
+                   !(ap->flags & ATA_FLAG_DISABLED)) {
+                       struct ata_queued_cmd *qc;
+
+                       qc = ata_qc_from_tag(ap, ap->link.active_tag);
+                       if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
+                           (qc->flags & ATA_QCFLAG_ACTIVE))
+                               handled |= bfin_ata_host_intr(ap, qc);
+               }
+       }
+
+       spin_unlock_irqrestore(&host->lock, flags);
+
+       return IRQ_RETVAL(handled);
+}
+
+
 static struct scsi_host_template bfin_sht = {
        ATA_BASE_SHT(DRV_NAME),
        .sg_tablesize           = SG_NONE,
        .dma_boundary           = ATA_DMA_BOUNDARY,
 };
 
-static const struct ata_port_operations bfin_pata_ops = {
+static struct ata_port_operations bfin_pata_ops = {
        .inherits               = &ata_sff_port_ops,
 
        .set_piomode            = bfin_set_piomode,
@@ -1370,7 +1487,6 @@ static const struct ata_port_operations bfin_pata_ops = {
        .thaw                   = bfin_thaw,
        .softreset              = bfin_softreset,
        .postreset              = bfin_postreset,
-       .post_internal_cmd      = bfin_bmdma_stop,
 
        .sff_irq_clear          = bfin_irq_clear,
        .sff_irq_on             = bfin_irq_on,
@@ -1507,7 +1623,7 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev)
        }
 
        if (ata_host_activate(host, platform_get_irq(pdev, 0),
-               ata_sff_interrupt, IRQF_SHARED, &bfin_sht) != 0) {
+               bfin_ata_interrupt, IRQF_SHARED, &bfin_sht) != 0) {
                peripheral_free_list(atapi_io_port);
                dev_err(&pdev->dev, "Fail to attach ATAPI device\n");
                return -ENODEV;
similarity index 72%
rename from drivers/ata/pata_rb500_cf.c
rename to drivers/ata/pata_rb532_cf.c
index 4345174aaeecc7fd8038bf45dc280aa73830701e..a108d259f19d73768423c10ec86e4b4b20c1c1a1 100644 (file)
@@ -32,7 +32,7 @@
 
 #include <asm/gpio.h>
 
-#define DRV_NAME       "pata-rb500-cf"
+#define DRV_NAME       "pata-rb532-cf"
 #define DRV_VERSION    "0.1.0"
 #define DRV_DESC       "PATA driver for RouterBOARD 532 Compact Flash"
 
@@ -43,7 +43,7 @@
 #define RB500_CF_REG_CTRL      0x080E
 #define RB500_CF_REG_DATA      0x0C00
 
-struct rb500_cf_info {
+struct rb532_cf_info {
        void __iomem    *iobase;
        unsigned int    gpio_line;
        int             frozen;
@@ -52,10 +52,10 @@ struct rb500_cf_info {
 
 /* ------------------------------------------------------------------------ */
 
-static inline void rb500_pata_finish_io(struct ata_port *ap)
+static inline void rb532_pata_finish_io(struct ata_port *ap)
 {
        struct ata_host *ah = ap->host;
-       struct rb500_cf_info *info = ah->private_data;
+       struct rb532_cf_info *info = ah->private_data;
 
        ata_sff_altstatus(ap);
        ndelay(RB500_CF_IO_DELAY);
@@ -63,14 +63,14 @@ static inline void rb500_pata_finish_io(struct ata_port *ap)
        set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
 }
 
-static void rb500_pata_exec_command(struct ata_port *ap,
+static void rb532_pata_exec_command(struct ata_port *ap,
                                const struct ata_taskfile *tf)
 {
        writeb(tf->command, ap->ioaddr.command_addr);
-       rb500_pata_finish_io(ap);
+       rb532_pata_finish_io(ap);
 }
 
-static void rb500_pata_data_xfer(struct ata_device *adev, unsigned char *buf,
+static void rb532_pata_data_xfer(struct ata_device *adev, unsigned char *buf,
                                unsigned int buflen, int write_data)
 {
        struct ata_port *ap = adev->link->ap;
@@ -84,27 +84,27 @@ static void rb500_pata_data_xfer(struct ata_device *adev, unsigned char *buf,
                        *buf = readb(ioaddr);
        }
 
-       rb500_pata_finish_io(adev->link->ap);
+       rb532_pata_finish_io(adev->link->ap);
 }
 
-static void rb500_pata_freeze(struct ata_port *ap)
+static void rb532_pata_freeze(struct ata_port *ap)
 {
-       struct rb500_cf_info *info = ap->host->private_data;
+       struct rb532_cf_info *info = ap->host->private_data;
 
        info->frozen = 1;
 }
 
-static void rb500_pata_thaw(struct ata_port *ap)
+static void rb532_pata_thaw(struct ata_port *ap)
 {
-       struct rb500_cf_info *info = ap->host->private_data;
+       struct rb532_cf_info *info = ap->host->private_data;
 
        info->frozen = 0;
 }
 
-static irqreturn_t rb500_pata_irq_handler(int irq, void *dev_instance)
+static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance)
 {
        struct ata_host *ah = dev_instance;
-       struct rb500_cf_info *info = ah->private_data;
+       struct rb532_cf_info *info = ah->private_data;
 
        if (gpio_get_value(info->gpio_line)) {
                set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW);
@@ -117,30 +117,30 @@ static irqreturn_t rb500_pata_irq_handler(int irq, void *dev_instance)
        return IRQ_HANDLED;
 }
 
-static struct ata_port_operations rb500_pata_port_ops = {
+static struct ata_port_operations rb532_pata_port_ops = {
        .inherits               = &ata_sff_port_ops,
-       .sff_exec_command       = rb500_pata_exec_command,
-       .sff_data_xfer          = rb500_pata_data_xfer,
-       .freeze                 = rb500_pata_freeze,
-       .thaw                   = rb500_pata_thaw,
+       .sff_exec_command       = rb532_pata_exec_command,
+       .sff_data_xfer          = rb532_pata_data_xfer,
+       .freeze                 = rb532_pata_freeze,
+       .thaw                   = rb532_pata_thaw,
 };
 
 /* ------------------------------------------------------------------------ */
 
-static struct scsi_host_template rb500_pata_sht = {
+static struct scsi_host_template rb532_pata_sht = {
        ATA_PIO_SHT(DRV_NAME),
 };
 
 /* ------------------------------------------------------------------------ */
 
-static void rb500_pata_setup_ports(struct ata_host *ah)
+static void rb532_pata_setup_ports(struct ata_host *ah)
 {
-       struct rb500_cf_info *info = ah->private_data;
+       struct rb532_cf_info *info = ah->private_data;
        struct ata_port *ap;
 
        ap = ah->ports[0];
 
-       ap->ops         = &rb500_pata_port_ops;
+       ap->ops         = &rb532_pata_port_ops;
        ap->pio_mask    = 0x1f; /* PIO4 */
        ap->flags       = ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO;
 
@@ -153,13 +153,13 @@ static void rb500_pata_setup_ports(struct ata_host *ah)
        ap->ioaddr.data_addr    = info->iobase + RB500_CF_REG_DATA;
 }
 
-static __devinit int rb500_pata_driver_probe(struct platform_device *pdev)
+static __devinit int rb532_pata_driver_probe(struct platform_device *pdev)
 {
        unsigned int irq;
        int gpio;
        struct resource *res;
        struct ata_host *ah;
-       struct rb500_cf_info *info;
+       struct rb532_cf_info *info;
        int ret;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -213,10 +213,10 @@ static __devinit int rb500_pata_driver_probe(struct platform_device *pdev)
                goto err_free_gpio;
        }
 
-       rb500_pata_setup_ports(ah);
+       rb532_pata_setup_ports(ah);
 
-       ret = ata_host_activate(ah, irq, rb500_pata_irq_handler,
-                               IRQF_TRIGGER_LOW, &rb500_pata_sht);
+       ret = ata_host_activate(ah, irq, rb532_pata_irq_handler,
+                               IRQF_TRIGGER_LOW, &rb532_pata_sht);
        if (ret)
                goto err_free_gpio;
 
@@ -228,10 +228,10 @@ err_free_gpio:
        return ret;
 }
 
-static __devexit int rb500_pata_driver_remove(struct platform_device *pdev)
+static __devexit int rb532_pata_driver_remove(struct platform_device *pdev)
 {
        struct ata_host *ah = platform_get_drvdata(pdev);
-       struct rb500_cf_info *info = ah->private_data;
+       struct rb532_cf_info *info = ah->private_data;
 
        ata_host_detach(ah);
        gpio_free(info->gpio_line);
@@ -242,9 +242,9 @@ static __devexit int rb500_pata_driver_remove(struct platform_device *pdev)
 /* work with hotplug and coldplug */
 MODULE_ALIAS("platform:" DRV_NAME);
 
-static struct platform_driver rb500_pata_platform_driver = {
-       .probe          = rb500_pata_driver_probe,
-       .remove         = __devexit_p(rb500_pata_driver_remove),
+static struct platform_driver rb532_pata_platform_driver = {
+       .probe          = rb532_pata_driver_probe,
+       .remove         = __devexit_p(rb532_pata_driver_remove),
        .driver  = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
@@ -255,16 +255,16 @@ static struct platform_driver rb500_pata_platform_driver = {
 
 #define DRV_INFO DRV_DESC " version " DRV_VERSION
 
-static int __init rb500_pata_module_init(void)
+static int __init rb532_pata_module_init(void)
 {
        printk(KERN_INFO DRV_INFO "\n");
 
-       return platform_driver_register(&rb500_pata_platform_driver);
+       return platform_driver_register(&rb532_pata_platform_driver);
 }
 
-static void __exit rb500_pata_module_exit(void)
+static void __exit rb532_pata_module_exit(void)
 {
-       platform_driver_unregister(&rb500_pata_platform_driver);
+       platform_driver_unregister(&rb532_pata_platform_driver);
 }
 
 MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");
@@ -273,5 +273,5 @@ MODULE_DESCRIPTION(DRV_DESC);
 MODULE_VERSION(DRV_VERSION);
 MODULE_LICENSE("GPL");
 
-module_init(rb500_pata_module_init);
-module_exit(rb500_pata_module_exit);
+module_init(rb532_pata_module_init);
+module_exit(rb532_pata_module_exit);
index d4840748fb5c902cfdd15bee9ee9c3b39081914d..2fea6cbe7755853b73331d09c1de61ccbba28a35 100644 (file)
@@ -464,11 +464,12 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        }
        pci_dev_put(isa);
 
-       /* 0x40 low bits indicate enabled channels */
-       pci_read_config_byte(pdev, 0x40 , &enable);
-       enable &= 3;
-       if (enable == 0) {
-               return -ENODEV;
+       if (!(config->flags & VIA_NO_ENABLES)) {
+               /* 0x40 low bits indicate enabled channels */
+               pci_read_config_byte(pdev, 0x40 , &enable);
+               enable &= 3;
+               if (enable == 0)
+                       return -ENODEV;
        }
 
        /* Initialise the FIFO for the enabled channels. */
index 26a6337195b3681587d2025a9a97519f01bf8ca1..842b1a15b78cadfafb5e031a8fe57245e6045380 100644 (file)
@@ -172,10 +172,11 @@ enum {
        PCIE_IRQ_MASK_OFS       = 0x1910,
        PCIE_UNMASK_ALL_IRQS    = 0x40a,        /* assorted bits */
 
-       HC_MAIN_IRQ_CAUSE_OFS   = 0x1d60,
-       HC_MAIN_IRQ_MASK_OFS    = 0x1d64,
-       HC_SOC_MAIN_IRQ_CAUSE_OFS = 0x20020,
-       HC_SOC_MAIN_IRQ_MASK_OFS = 0x20024,
+       /* Host Controller Main Interrupt Cause/Mask registers (1 per-chip) */
+       PCI_HC_MAIN_IRQ_CAUSE_OFS = 0x1d60,
+       PCI_HC_MAIN_IRQ_MASK_OFS  = 0x1d64,
+       SOC_HC_MAIN_IRQ_CAUSE_OFS = 0x20020,
+       SOC_HC_MAIN_IRQ_MASK_OFS  = 0x20024,
        ERR_IRQ                 = (1 << 0),     /* shift by port # */
        DONE_IRQ                = (1 << 1),     /* shift by port # */
        HC0_IRQ_PEND            = 0x1ff,        /* bits 0-8 = HC0's ports */
@@ -445,8 +446,8 @@ struct mv_host_priv {
        const struct mv_hw_ops  *ops;
        int                     n_ports;
        void __iomem            *base;
-       void __iomem            *main_cause_reg_addr;
-       void __iomem            *main_mask_reg_addr;
+       void __iomem            *main_irq_cause_addr;
+       void __iomem            *main_irq_mask_addr;
        u32                     irq_cause_ofs;
        u32                     irq_mask_ofs;
        u32                     unmask_all_irqs;
@@ -727,8 +728,8 @@ static inline unsigned int mv_hardport_from_port(unsigned int port)
  * Simple code, with two return values, so macro rather than inline.
  *
  * port is the sole input, in range 0..7.
- * shift is one output, for use with the main_cause and main_mask registers.
- * hardport is the other output, in range 0..3
+ * shift is one output, for use with main_irq_cause / main_irq_mask registers.
+ * hardport is the other output, in range 0..3.
  *
  * Note that port and hardport may be the same variable in some cases.
  */
@@ -1679,12 +1680,12 @@ static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp
 /**
  *      mv_host_intr - Handle all interrupts on the given host controller
  *      @host: host specific structure
- *      @main_cause: Main interrupt cause register for the chip.
+ *      @main_irq_cause: Main interrupt cause register for the chip.
  *
  *      LOCKING:
  *      Inherited from caller.
  */
-static int mv_host_intr(struct ata_host *host, u32 main_cause)
+static int mv_host_intr(struct ata_host *host, u32 main_irq_cause)
 {
        struct mv_host_priv *hpriv = host->private_data;
        void __iomem *mmio = hpriv->base, *hc_mmio = NULL;
@@ -1705,7 +1706,7 @@ static int mv_host_intr(struct ata_host *host, u32 main_cause)
                 * Do nothing if port is not interrupting or is disabled:
                 */
                MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
-               port_cause = (main_cause >> shift) & (DONE_IRQ | ERR_IRQ);
+               port_cause = (main_irq_cause >> shift) & (DONE_IRQ | ERR_IRQ);
                if (!port_cause || !ap || (ap->flags & ATA_FLAG_DISABLED))
                        continue;
                /*
@@ -1811,20 +1812,20 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
        struct ata_host *host = dev_instance;
        struct mv_host_priv *hpriv = host->private_data;
        unsigned int handled = 0;
-       u32 main_cause, main_mask;
+       u32 main_irq_cause, main_irq_mask;
 
        spin_lock(&host->lock);
-       main_cause = readl(hpriv->main_cause_reg_addr);
-       main_mask  = readl(hpriv->main_mask_reg_addr);
+       main_irq_cause = readl(hpriv->main_irq_cause_addr);
+       main_irq_mask  = readl(hpriv->main_irq_mask_addr);
        /*
         * Deal with cases where we either have nothing pending, or have read
         * a bogus register value which can indicate HW removal or PCI fault.
         */
-       if ((main_cause & main_mask) && (main_cause != 0xffffffffU)) {
-               if (unlikely((main_cause & PCI_ERR) && HAS_PCI(host)))
+       if ((main_irq_cause & main_irq_mask) && (main_irq_cause != 0xffffffffU)) {
+               if (unlikely((main_irq_cause & PCI_ERR) && HAS_PCI(host)))
                        handled = mv_pci_error(host, hpriv->base);
                else
-                       handled = mv_host_intr(host, main_cause);
+                       handled = mv_host_intr(host, main_irq_cause);
        }
        spin_unlock(&host->lock);
        return IRQ_RETVAL(handled);
@@ -2027,7 +2028,7 @@ static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio)
        ZERO(MV_PCI_DISC_TIMER);
        ZERO(MV_PCI_MSI_TRIGGER);
        writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT);
-       ZERO(HC_MAIN_IRQ_MASK_OFS);
+       ZERO(PCI_HC_MAIN_IRQ_MASK_OFS);
        ZERO(MV_PCI_SERR_MASK);
        ZERO(hpriv->irq_cause_ofs);
        ZERO(hpriv->irq_mask_ofs);
@@ -2404,7 +2405,7 @@ static void mv_eh_freeze(struct ata_port *ap)
 {
        struct mv_host_priv *hpriv = ap->host->private_data;
        unsigned int shift, hardport, port = ap->port_no;
-       u32 main_mask;
+       u32 main_irq_mask;
 
        /* FIXME: handle coalescing completion events properly */
 
@@ -2412,9 +2413,9 @@ static void mv_eh_freeze(struct ata_port *ap)
        MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
 
        /* disable assertion of portN err, done events */
-       main_mask = readl(hpriv->main_mask_reg_addr);
-       main_mask &= ~((DONE_IRQ | ERR_IRQ) << shift);
-       writelfl(main_mask, hpriv->main_mask_reg_addr);
+       main_irq_mask = readl(hpriv->main_irq_mask_addr);
+       main_irq_mask &= ~((DONE_IRQ | ERR_IRQ) << shift);
+       writelfl(main_irq_mask, hpriv->main_irq_mask_addr);
 }
 
 static void mv_eh_thaw(struct ata_port *ap)
@@ -2423,7 +2424,7 @@ static void mv_eh_thaw(struct ata_port *ap)
        unsigned int shift, hardport, port = ap->port_no;
        void __iomem *hc_mmio = mv_hc_base_from_port(hpriv->base, port);
        void __iomem *port_mmio = mv_ap_base(ap);
-       u32 main_mask, hc_irq_cause;
+       u32 main_irq_mask, hc_irq_cause;
 
        /* FIXME: handle coalescing completion events properly */
 
@@ -2438,9 +2439,9 @@ static void mv_eh_thaw(struct ata_port *ap)
        writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
 
        /* enable assertion of portN err, done events */
-       main_mask = readl(hpriv->main_mask_reg_addr);
-       main_mask |= ((DONE_IRQ | ERR_IRQ) << shift);
-       writelfl(main_mask, hpriv->main_mask_reg_addr);
+       main_irq_mask = readl(hpriv->main_irq_mask_addr);
+       main_irq_mask |= ((DONE_IRQ | ERR_IRQ) << shift);
+       writelfl(main_irq_mask, hpriv->main_irq_mask_addr);
 }
 
 /**
@@ -2654,15 +2655,15 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
                goto done;
 
        if (HAS_PCI(host)) {
-               hpriv->main_cause_reg_addr = mmio + HC_MAIN_IRQ_CAUSE_OFS;
-               hpriv->main_mask_reg_addr  = mmio + HC_MAIN_IRQ_MASK_OFS;
+               hpriv->main_irq_cause_addr = mmio + PCI_HC_MAIN_IRQ_CAUSE_OFS;
+               hpriv->main_irq_mask_addr  = mmio + PCI_HC_MAIN_IRQ_MASK_OFS;
        } else {
-               hpriv->main_cause_reg_addr = mmio + HC_SOC_MAIN_IRQ_CAUSE_OFS;
-               hpriv->main_mask_reg_addr  = mmio + HC_SOC_MAIN_IRQ_MASK_OFS;
+               hpriv->main_irq_cause_addr = mmio + SOC_HC_MAIN_IRQ_CAUSE_OFS;
+               hpriv->main_irq_mask_addr  = mmio + SOC_HC_MAIN_IRQ_MASK_OFS;
        }
 
        /* global interrupt mask: 0 == mask everything */
-       writel(0, hpriv->main_mask_reg_addr);
+       writel(0, hpriv->main_irq_mask_addr);
 
        n_hc = mv_get_hc_count(host->ports[0]->flags);
 
@@ -2712,23 +2713,23 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
                writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs);
                if (IS_GEN_I(hpriv))
                        writelfl(~HC_MAIN_MASKED_IRQS_5,
-                                hpriv->main_mask_reg_addr);
+                                hpriv->main_irq_mask_addr);
                else
                        writelfl(~HC_MAIN_MASKED_IRQS,
-                                hpriv->main_mask_reg_addr);
+                                hpriv->main_irq_mask_addr);
 
                VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
                        "PCI int cause/mask=0x%08x/0x%08x\n",
-                       readl(hpriv->main_cause_reg_addr),
-                       readl(hpriv->main_mask_reg_addr),
+                       readl(hpriv->main_irq_cause_addr),
+                       readl(hpriv->main_irq_mask_addr),
                        readl(mmio + hpriv->irq_cause_ofs),
                        readl(mmio + hpriv->irq_mask_ofs));
        } else {
                writelfl(~HC_MAIN_MASKED_IRQS_SOC,
-                        hpriv->main_mask_reg_addr);
+                        hpriv->main_irq_mask_addr);
                VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x\n",
-                       readl(hpriv->main_cause_reg_addr),
-                       readl(hpriv->main_mask_reg_addr));
+                       readl(hpriv->main_irq_cause_addr),
+                       readl(hpriv->main_irq_mask_addr));
        }
 done:
        return rc;
index 9248e0927d0873062800a4fd10ee2746bb956c34..be288b5e41809cbd8f991b4a953d4850604ea4a9 100644 (file)
@@ -787,6 +787,10 @@ int device_add(struct device *dev)
        parent = get_device(dev->parent);
        setup_parent(dev, parent);
 
+       /* use parent numa_node */
+       if (parent)
+               set_dev_node(dev, dev_to_node(parent));
+
        /* first, register with generic layer. */
        error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev->bus_id);
        if (error)
@@ -1306,8 +1310,11 @@ int device_move(struct device *dev, struct device *new_parent)
        dev->parent = new_parent;
        if (old_parent)
                klist_remove(&dev->knode_parent);
-       if (new_parent)
+       if (new_parent) {
                klist_add_tail(&dev->knode_parent, &new_parent->klist_children);
+               set_dev_node(dev, dev_to_node(new_parent));
+       }
+
        if (!dev->class)
                goto out_put;
        error = device_move_class_links(dev, old_parent, new_parent);
@@ -1317,9 +1324,12 @@ int device_move(struct device *dev, struct device *new_parent)
                if (!kobject_move(&dev->kobj, &old_parent->kobj)) {
                        if (new_parent)
                                klist_remove(&dev->knode_parent);
-                       if (old_parent)
+                       dev->parent = old_parent;
+                       if (old_parent) {
                                klist_add_tail(&dev->knode_parent,
                                               &old_parent->klist_children);
+                               set_dev_node(dev, dev_to_node(old_parent));
+                       }
                }
                cleanup_glue_dir(dev, new_parent_kobj);
                put_device(new_parent);
index 1fef7df8c9d601417312c088a6c0b8b9351646c8..9fd4a8534146e1747160e0a987fe8e4224eae01f 100644 (file)
@@ -396,6 +396,8 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
        if (!firmware_p)
                return -EINVAL;
 
+       printk(KERN_INFO "firmware: requesting %s\n", name);
+
        *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
        if (!firmware) {
                printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n",
index 12fde2d03d695a112f02debd25c4fb897a4b937c..39f3d1b3a21354aa112f5fb222b862d99daafb04 100644 (file)
@@ -77,6 +77,7 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
                       "Node %d PageTables:   %8lu kB\n"
                       "Node %d NFS_Unstable: %8lu kB\n"
                       "Node %d Bounce:       %8lu kB\n"
+                      "Node %d WritebackTmp: %8lu kB\n"
                       "Node %d Slab:         %8lu kB\n"
                       "Node %d SReclaimable: %8lu kB\n"
                       "Node %d SUnreclaim:   %8lu kB\n",
@@ -99,6 +100,7 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
                       nid, K(node_page_state(nid, NR_PAGETABLE)),
                       nid, K(node_page_state(nid, NR_UNSTABLE_NFS)),
                       nid, K(node_page_state(nid, NR_BOUNCE)),
+                      nid, K(node_page_state(nid, NR_WRITEBACK_TEMP)),
                       nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE) +
                                node_page_state(nid, NR_SLAB_UNRECLAIMABLE)),
                       nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE)),
index 280e71ee744ca659e164cdb0d266b11efb3383ba..5b4c6e649c11170803a8ed7bedc7ca333c69a99a 100644 (file)
@@ -195,7 +195,6 @@ void aoedev_exit(void);
 struct aoedev *aoedev_by_aoeaddr(int maj, int min);
 struct aoedev *aoedev_by_sysminor_m(ulong sysminor);
 void aoedev_downdev(struct aoedev *d);
-int aoedev_isbusy(struct aoedev *d);
 int aoedev_flush(const char __user *str, size_t size);
 
 int aoenet_init(void);
index d00293ba3b456187a21b1b2aa6fa5ccff49c0dfc..8fc429cf82b6b41d9ddf91d41a339831ac96a778 100644 (file)
@@ -668,16 +668,16 @@ ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id)
        u16 n;
 
        /* word 83: command set supported */
-       n = le16_to_cpu(get_unaligned((__le16 *) &id[83<<1]));
+       n = get_unaligned_le16(&id[83 << 1]);
 
        /* word 86: command set/feature enabled */
-       n |= le16_to_cpu(get_unaligned((__le16 *) &id[86<<1]));
+       n |= get_unaligned_le16(&id[86 << 1]);
 
        if (n & (1<<10)) {      /* bit 10: LBA 48 */
                d->flags |= DEVFL_EXT;
 
                /* word 100: number lba48 sectors */
-               ssize = le64_to_cpu(get_unaligned((__le64 *) &id[100<<1]));
+               ssize = get_unaligned_le64(&id[100 << 1]);
 
                /* set as in ide-disk.c:init_idedisk_capacity */
                d->geo.cylinders = ssize;
@@ -688,12 +688,12 @@ ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id)
                d->flags &= ~DEVFL_EXT;
 
                /* number lba28 sectors */
-               ssize = le32_to_cpu(get_unaligned((__le32 *) &id[60<<1]));
+               ssize = get_unaligned_le32(&id[60 << 1]);
 
                /* NOTE: obsolete in ATA 6 */
-               d->geo.cylinders = le16_to_cpu(get_unaligned((__le16 *) &id[54<<1]));
-               d->geo.heads = le16_to_cpu(get_unaligned((__le16 *) &id[55<<1]));
-               d->geo.sectors = le16_to_cpu(get_unaligned((__le16 *) &id[56<<1]));
+               d->geo.cylinders = get_unaligned_le16(&id[54 << 1]);
+               d->geo.heads = get_unaligned_le16(&id[55 << 1]);
+               d->geo.sectors = get_unaligned_le16(&id[56 << 1]);
        }
 
        if (d->ssize != ssize)
@@ -779,7 +779,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)
        u16 aoemajor;
 
        hin = (struct aoe_hdr *) skb_mac_header(skb);
-       aoemajor = be16_to_cpu(get_unaligned(&hin->major));
+       aoemajor = get_unaligned_be16(&hin->major);
        d = aoedev_by_aoeaddr(aoemajor, hin->minor);
        if (d == NULL) {
                snprintf(ebuf, sizeof ebuf, "aoecmd_ata_rsp: ata response "
@@ -791,7 +791,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)
 
        spin_lock_irqsave(&d->lock, flags);
 
-       n = be32_to_cpu(get_unaligned(&hin->tag));
+       n = get_unaligned_be32(&hin->tag);
        t = gettgt(d, hin->src);
        if (t == NULL) {
                printk(KERN_INFO "aoe: can't find target e%ld.%d:%012llx\n",
@@ -806,9 +806,9 @@ aoecmd_ata_rsp(struct sk_buff *skb)
                snprintf(ebuf, sizeof ebuf,
                        "%15s e%d.%d    tag=%08x@%08lx\n",
                        "unexpected rsp",
-                       be16_to_cpu(get_unaligned(&hin->major)),
+                       get_unaligned_be16(&hin->major),
                        hin->minor,
-                       be32_to_cpu(get_unaligned(&hin->tag)),
+                       get_unaligned_be32(&hin->tag),
                        jiffies);
                aoechr_error(ebuf);
                return;
@@ -873,7 +873,7 @@ aoecmd_ata_rsp(struct sk_buff *skb)
                        printk(KERN_INFO
                                "aoe: unrecognized ata command %2.2Xh for %d.%d\n",
                                ahout->cmdstat,
-                               be16_to_cpu(get_unaligned(&hin->major)),
+                               get_unaligned_be16(&hin->major),
                                hin->minor);
                }
        }
index f9a1cd9edb77e156e5a7f81c389f26ea21161f41..a1d813ab0d6b6046b7d1a1e34ac3d60fd4b68179 100644 (file)
@@ -18,24 +18,6 @@ static void skbpoolfree(struct aoedev *d);
 static struct aoedev *devlist;
 static DEFINE_SPINLOCK(devlist_lock);
 
-int
-aoedev_isbusy(struct aoedev *d)
-{
-       struct aoetgt **t, **te;
-       struct frame *f, *e;
-
-       t = d->targets;
-       te = t + NTARGETS;
-       for (; t < te && *t; t++) {
-               f = (*t)->frames;
-               e = f + (*t)->nframes;
-               for (; f < e; f++)
-                       if (f->tag != FREETAG)
-                               return 1;
-       }
-       return 0;
-}
-
 struct aoedev *
 aoedev_by_aoeaddr(int maj, int min)
 {
index 18d243c73eee0b34966a1a4eea6da1e673ece772..d625169c8e48a99951cbb3f833755f77ee0eca1f 100644 (file)
@@ -128,7 +128,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
        skb_push(skb, ETH_HLEN);        /* (1) */
 
        h = (struct aoe_hdr *) skb_mac_header(skb);
-       n = be32_to_cpu(get_unaligned(&h->tag));
+       n = get_unaligned_be32(&h->tag);
        if ((h->verfl & AOEFL_RSP) == 0 || (n & 1<<31))
                goto exit;
 
@@ -140,7 +140,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
                        printk(KERN_ERR
                                "%s%d.%d@%s; ecode=%d '%s'\n",
                                "aoe: error packet from ",
-                               be16_to_cpu(get_unaligned(&h->major)),
+                               get_unaligned_be16(&h->major),
                                h->minor, skb->dev->name,
                                h->err, aoe_errlist[n]);
                goto exit;
index e8e38faeafd8774d423366424ee60cf33c99338f..a196ef7f147fa234ead35696b8c115dd9ea69927 100644 (file)
@@ -387,10 +387,14 @@ static struct block_device_operations brd_fops = {
  */
 static int rd_nr;
 int rd_size = CONFIG_BLK_DEV_RAM_SIZE;
+static int max_part;
+static int part_shift;
 module_param(rd_nr, int, 0);
 MODULE_PARM_DESC(rd_nr, "Maximum number of brd devices");
 module_param(rd_size, int, 0);
 MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes.");
+module_param(max_part, int, 0);
+MODULE_PARM_DESC(max_part, "Maximum number of partitions per RAM disk");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_BLOCKDEV_MAJOR(RAMDISK_MAJOR);
 
@@ -435,11 +439,11 @@ static struct brd_device *brd_alloc(int i)
        blk_queue_max_sectors(brd->brd_queue, 1024);
        blk_queue_bounce_limit(brd->brd_queue, BLK_BOUNCE_ANY);
 
-       disk = brd->brd_disk = alloc_disk(1);
+       disk = brd->brd_disk = alloc_disk(1 << part_shift);
        if (!disk)
                goto out_free_queue;
        disk->major             = RAMDISK_MAJOR;
-       disk->first_minor       = i;
+       disk->first_minor       = i << part_shift;
        disk->fops              = &brd_fops;
        disk->private_data      = brd;
        disk->queue             = brd->brd_queue;
@@ -523,7 +527,12 @@ static int __init brd_init(void)
         *     themselves and have kernel automatically instantiate actual
         *     device on-demand.
         */
-       if (rd_nr > 1UL << MINORBITS)
+
+       part_shift = 0;
+       if (max_part > 0)
+               part_shift = fls(max_part);
+
+       if (rd_nr > 1UL << (MINORBITS - part_shift))
                return -EINVAL;
 
        if (rd_nr) {
@@ -531,7 +540,7 @@ static int __init brd_init(void)
                range = rd_nr;
        } else {
                nr = CONFIG_BLK_DEV_RAM_COUNT;
-               range = 1UL << MINORBITS;
+               range = 1UL << (MINORBITS - part_shift);
        }
 
        if (register_blkdev(RAMDISK_MAJOR, "ramdisk"))
@@ -570,7 +579,7 @@ static void __exit brd_exit(void)
        unsigned long range;
        struct brd_device *brd, *next;
 
-       range = rd_nr ? rd_nr :  1UL << MINORBITS;
+       range = rd_nr ? rd_nr :  1UL << (MINORBITS - part_shift);
 
        list_for_each_entry_safe(brd, next, &brd_devices, brd_list)
                brd_del_one(brd);
index cf6083a1f9280e5f0008363de88c532abb04b527..e539be5750dc694703af89853fee7a41ffed5bac 100644 (file)
@@ -425,7 +425,7 @@ static void __devinit cciss_procinit(int i)
        struct proc_dir_entry *pde;
 
        if (proc_cciss == NULL)
-               proc_cciss = proc_mkdir("cciss", proc_root_driver);
+               proc_cciss = proc_mkdir("driver/cciss", NULL);
        if (!proc_cciss)
                return;
        pde = proc_create(hba[i]->devname, S_IWUSR | S_IRUSR | S_IRGRP |
@@ -3700,7 +3700,7 @@ static void __exit cciss_cleanup(void)
                        cciss_remove_one(hba[i]->pdev);
                }
        }
-       remove_proc_entry("cciss", proc_root_driver);
+       remove_proc_entry("driver/cciss", NULL);
 }
 
 static void fail_all_cmds(unsigned long ctlr)
index 69199185ff4b8acba9e4cdaca15e2521263ec1d0..09c14341e6e39582c4230d71ec8bddb384e26610 100644 (file)
@@ -214,7 +214,7 @@ static struct proc_dir_entry *proc_array;
 static void __init ida_procinit(int i)
 {
        if (proc_array == NULL) {
-               proc_array = proc_mkdir("cpqarray", proc_root_driver);
+               proc_array = proc_mkdir("driver/cpqarray", NULL);
                if (!proc_array) return;
        }
 
@@ -1796,7 +1796,7 @@ static void __exit cpqarray_exit(void)
                }
        }
 
-       remove_proc_entry("cpqarray", proc_root_driver);
+       remove_proc_entry("driver/cpqarray", NULL);
 }
 
 module_init(cpqarray_init)
index 7652e87d60c52cb7c2a18053198fd205ec1ef9b2..395f8ea7981c54f2fc5b6dfec3cf99acfd83e1ff 100644 (file)
@@ -4526,14 +4526,15 @@ static void __init parse_floppy_cfg_string(char *cfg)
        }
 }
 
-int __init init_module(void)
+static int __init floppy_module_init(void)
 {
        if (floppy)
                parse_floppy_cfg_string(floppy);
        return floppy_init();
 }
+module_init(floppy_module_init);
 
-void cleanup_module(void)
+static void __exit floppy_module_exit(void)
 {
        int drive;
 
@@ -4562,6 +4563,7 @@ void cleanup_module(void)
        /* eject disk, if any */
        fd_eject(0);
 }
+module_exit(floppy_module_exit);
 
 module_param(floppy, charp, 0);
 module_param(FLOPPY_IRQ, int, 0);
index f7f163557aa0f3ea88bd1bf91efd41942b59dfc0..d3a25b027ff9fc5e6331372a252b5e134b6270c4 100644 (file)
@@ -546,7 +546,7 @@ static void loop_unplug(struct request_queue *q)
 {
        struct loop_device *lo = q->queuedata;
 
-       clear_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags);
+       queue_flag_clear_unlocked(QUEUE_FLAG_PLUGGED, q);
        blk_run_address_space(lo->lo_backing_file->f_mapping);
 }
 
index 60cc54368b66eaa1c7888ab905f7c9b83c92bd41..ad98dda6037dd5193baa266bf2471c52ca1b6f79 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/kernel.h>
 #include <net/sock.h>
 #include <linux/net.h>
+#include <linux/kthread.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -55,6 +56,7 @@ static unsigned int debugflags;
 
 static unsigned int nbds_max = 16;
 static struct nbd_device *nbd_dev;
+static int max_part;
 
 /*
  * Use just one lock (or at most 1 per NIC). Two arguments for this:
@@ -337,7 +339,7 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
        }
 
        req = nbd_find_request(lo, *(struct request **)reply.handle);
-       if (unlikely(IS_ERR(req))) {
+       if (IS_ERR(req)) {
                result = PTR_ERR(req);
                if (result != -ENOENT)
                        goto harderror;
@@ -441,6 +443,85 @@ static void nbd_clear_que(struct nbd_device *lo)
 }
 
 
+static void nbd_handle_req(struct nbd_device *lo, struct request *req)
+{
+       if (!blk_fs_request(req))
+               goto error_out;
+
+       nbd_cmd(req) = NBD_CMD_READ;
+       if (rq_data_dir(req) == WRITE) {
+               nbd_cmd(req) = NBD_CMD_WRITE;
+               if (lo->flags & NBD_READ_ONLY) {
+                       printk(KERN_ERR "%s: Write on read-only\n",
+                                       lo->disk->disk_name);
+                       goto error_out;
+               }
+       }
+
+       req->errors = 0;
+
+       mutex_lock(&lo->tx_lock);
+       if (unlikely(!lo->sock)) {
+               mutex_unlock(&lo->tx_lock);
+               printk(KERN_ERR "%s: Attempted send on closed socket\n",
+                      lo->disk->disk_name);
+               req->errors++;
+               nbd_end_request(req);
+               return;
+       }
+
+       lo->active_req = req;
+
+       if (nbd_send_req(lo, req) != 0) {
+               printk(KERN_ERR "%s: Request send failed\n",
+                               lo->disk->disk_name);
+               req->errors++;
+               nbd_end_request(req);
+       } else {
+               spin_lock(&lo->queue_lock);
+               list_add(&req->queuelist, &lo->queue_head);
+               spin_unlock(&lo->queue_lock);
+       }
+
+       lo->active_req = NULL;
+       mutex_unlock(&lo->tx_lock);
+       wake_up_all(&lo->active_wq);
+
+       return;
+
+error_out:
+       req->errors++;
+       nbd_end_request(req);
+}
+
+static int nbd_thread(void *data)
+{
+       struct nbd_device *lo = data;
+       struct request *req;
+
+       set_user_nice(current, -20);
+       while (!kthread_should_stop() || !list_empty(&lo->waiting_queue)) {
+               /* wait for something to do */
+               wait_event_interruptible(lo->waiting_wq,
+                                        kthread_should_stop() ||
+                                        !list_empty(&lo->waiting_queue));
+
+               /* extract request */
+               if (list_empty(&lo->waiting_queue))
+                       continue;
+
+               spin_lock_irq(&lo->queue_lock);
+               req = list_entry(lo->waiting_queue.next, struct request,
+                                queuelist);
+               list_del_init(&req->queuelist);
+               spin_unlock_irq(&lo->queue_lock);
+
+               /* handle request */
+               nbd_handle_req(lo, req);
+       }
+       return 0;
+}
+
 /*
  * We always wait for result of write, for now. It would be nice to make it optional
  * in future
@@ -456,65 +537,23 @@ static void do_nbd_request(struct request_queue * q)
                struct nbd_device *lo;
 
                blkdev_dequeue_request(req);
+
+               spin_unlock_irq(q->queue_lock);
+
                dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n",
                                req->rq_disk->disk_name, req, req->cmd_type);
 
-               if (!blk_fs_request(req))
-                       goto error_out;
-
                lo = req->rq_disk->private_data;
 
                BUG_ON(lo->magic != LO_MAGIC);
 
-               nbd_cmd(req) = NBD_CMD_READ;
-               if (rq_data_dir(req) == WRITE) {
-                       nbd_cmd(req) = NBD_CMD_WRITE;
-                       if (lo->flags & NBD_READ_ONLY) {
-                               printk(KERN_ERR "%s: Write on read-only\n",
-                                               lo->disk->disk_name);
-                               goto error_out;
-                       }
-               }
-
-               req->errors = 0;
-               spin_unlock_irq(q->queue_lock);
-
-               mutex_lock(&lo->tx_lock);
-               if (unlikely(!lo->sock)) {
-                       mutex_unlock(&lo->tx_lock);
-                       printk(KERN_ERR "%s: Attempted send on closed socket\n",
-                              lo->disk->disk_name);
-                       req->errors++;
-                       nbd_end_request(req);
-                       spin_lock_irq(q->queue_lock);
-                       continue;
-               }
-
-               lo->active_req = req;
+               spin_lock_irq(&lo->queue_lock);
+               list_add_tail(&req->queuelist, &lo->waiting_queue);
+               spin_unlock_irq(&lo->queue_lock);
 
-               if (nbd_send_req(lo, req) != 0) {
-                       printk(KERN_ERR "%s: Request send failed\n",
-                                       lo->disk->disk_name);
-                       req->errors++;
-                       nbd_end_request(req);
-               } else {
-                       spin_lock(&lo->queue_lock);
-                       list_add(&req->queuelist, &lo->queue_head);
-                       spin_unlock(&lo->queue_lock);
-               }
-
-               lo->active_req = NULL;
-               mutex_unlock(&lo->tx_lock);
-               wake_up_all(&lo->active_wq);
+               wake_up(&lo->waiting_wq);
 
                spin_lock_irq(q->queue_lock);
-               continue;
-
-error_out:
-               req->errors++;
-               spin_unlock(q->queue_lock);
-               nbd_end_request(req);
-               spin_lock(q->queue_lock);
        }
 }
 
@@ -524,6 +563,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
        struct nbd_device *lo = inode->i_bdev->bd_disk->private_data;
        int error;
        struct request sreq ;
+       struct task_struct *thread;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -537,6 +577,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
        switch (cmd) {
        case NBD_DISCONNECT:
                printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name);
+               blk_rq_init(NULL, &sreq);
                sreq.cmd_type = REQ_TYPE_SPECIAL;
                nbd_cmd(&sreq) = NBD_CMD_DISC;
                /*
@@ -571,10 +612,13 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
                error = -EINVAL;
                file = fget(arg);
                if (file) {
+                       struct block_device *bdev = inode->i_bdev;
                        inode = file->f_path.dentry->d_inode;
                        if (S_ISSOCK(inode->i_mode)) {
                                lo->file = file;
                                lo->sock = SOCKET_I(inode);
+                               if (max_part > 0)
+                                       bdev->bd_invalidated = 1;
                                error = 0;
                        } else {
                                fput(file);
@@ -606,7 +650,12 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
        case NBD_DO_IT:
                if (!lo->file)
                        return -EINVAL;
+               thread = kthread_create(nbd_thread, lo, lo->disk->disk_name);
+               if (IS_ERR(thread))
+                       return PTR_ERR(thread);
+               wake_up_process(thread);
                error = nbd_do_it(lo);
+               kthread_stop(thread);
                if (error)
                        return error;
                sock_shutdown(lo, 1);
@@ -619,6 +668,8 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
                lo->bytesize = 0;
                inode->i_bdev->bd_inode->i_size = 0;
                set_capacity(lo->disk, 0);
+               if (max_part > 0)
+                       ioctl_by_bdev(inode->i_bdev, BLKRRPART, 0);
                return lo->harderror;
        case NBD_CLEAR_QUE:
                /*
@@ -652,6 +703,7 @@ static int __init nbd_init(void)
 {
        int err = -ENOMEM;
        int i;
+       int part_shift;
 
        BUILD_BUG_ON(sizeof(struct nbd_request) != 28);
 
@@ -659,8 +711,17 @@ static int __init nbd_init(void)
        if (!nbd_dev)
                return -ENOMEM;
 
+       if (max_part < 0) {
+               printk(KERN_CRIT "nbd: max_part must be >= 0\n");
+               return -EINVAL;
+       }
+
+       part_shift = 0;
+       if (max_part > 0)
+               part_shift = fls(max_part);
+
        for (i = 0; i < nbds_max; i++) {
-               struct gendisk *disk = alloc_disk(1);
+               struct gendisk *disk = alloc_disk(1 << part_shift);
                elevator_t *old_e;
                if (!disk)
                        goto out;
@@ -695,17 +756,18 @@ static int __init nbd_init(void)
                nbd_dev[i].file = NULL;
                nbd_dev[i].magic = LO_MAGIC;
                nbd_dev[i].flags = 0;
+               INIT_LIST_HEAD(&nbd_dev[i].waiting_queue);
                spin_lock_init(&nbd_dev[i].queue_lock);
                INIT_LIST_HEAD(&nbd_dev[i].queue_head);
                mutex_init(&nbd_dev[i].tx_lock);
                init_waitqueue_head(&nbd_dev[i].active_wq);
+               init_waitqueue_head(&nbd_dev[i].waiting_wq);
                nbd_dev[i].blksize = 1024;
                nbd_dev[i].bytesize = 0;
                disk->major = NBD_MAJOR;
-               disk->first_minor = i;
+               disk->first_minor = i << part_shift;
                disk->fops = &nbd_fops;
                disk->private_data = &nbd_dev[i];
-               disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;
                sprintf(disk->disk_name, "nbd%d", i);
                set_capacity(disk, 0);
                add_disk(disk);
@@ -743,7 +805,9 @@ MODULE_DESCRIPTION("Network Block Device");
 MODULE_LICENSE("GPL");
 
 module_param(nbds_max, int, 0444);
-MODULE_PARM_DESC(nbds_max, "How many network block devices to initialize.");
+MODULE_PARM_DESC(nbds_max, "number of network block devices to initialize (default: 16)");
+module_param(max_part, int, 0444);
+MODULE_PARM_DESC(max_part, "number of partitions per device (default: 0)");
 #ifndef NDEBUG
 module_param(debugflags, int, 0644);
 MODULE_PARM_DESC(debugflags, "flags for controlling debug output");
index df819f8a95a6d0db78e95153e0194deea4730e88..570f3b70dce795afc8e1beabd104de3dc31e26ad 100644 (file)
@@ -716,10 +716,8 @@ static int pd_special_command(struct pd_unit *disk,
        struct request rq;
        int err = 0;
 
-       memset(&rq, 0, sizeof(rq));
-       rq.errors = 0;
+       blk_rq_init(NULL, &rq);
        rq.rq_disk = disk->gd;
-       rq.ref_count = 1;
        rq.end_io_data = &wait;
        rq.end_io = blk_end_sync_rq;
        blk_insert_request(disk->gd->queue, &rq, 0, func);
index 18feb1c7c33b1b03ec0d394767e252b466000876..3ba1df93e9e32e8fb3c8641f7f11b9a33a575cc2 100644 (file)
@@ -776,8 +776,6 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
 
        rq->cmd_len = COMMAND_SIZE(cgc->cmd[0]);
        memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE);
-       if (sizeof(rq->cmd) > CDROM_PACKET_SIZE)
-               memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE);
 
        rq->timeout = 60*HZ;
        rq->cmd_type = REQ_TYPE_BLOCK_PC;
@@ -2744,7 +2742,6 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
        int i;
        int ret = 0;
        char b[BDEVNAME_SIZE];
-       struct proc_dir_entry *proc;
        struct block_device *bdev;
 
        if (pd->pkt_dev == dev) {
@@ -2788,11 +2785,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
                goto out_mem;
        }
 
-       proc = create_proc_entry(pd->name, 0, pkt_proc);
-       if (proc) {
-               proc->data = pd;
-               proc->proc_fops = &pkt_proc_fops;
-       }
+       proc_create_data(pd->name, 0, pkt_proc, &pkt_proc_fops, pd);
        DPRINTK(DRIVER_NAME": writer %s mapped to %s\n", pd->name, bdevname(bdev, b));
        return 0;
 
@@ -3101,7 +3094,7 @@ static int __init pkt_init(void)
                goto out_misc;
        }
 
-       pkt_proc = proc_mkdir(DRIVER_NAME, proc_root_driver);
+       pkt_proc = proc_mkdir("driver/"DRIVER_NAME, NULL);
 
        return 0;
 
@@ -3117,7 +3110,7 @@ out2:
 
 static void __exit pkt_exit(void)
 {
-       remove_proc_entry(DRIVER_NAME, proc_root_driver);
+       remove_proc_entry("driver/"DRIVER_NAME, NULL);
        misc_deregister(&pkt_misc);
 
        pkt_debugfs_cleanup();
index 7483f947f0e995d435585508daaa8583be926b3a..d797e209951d43fe2163e91e32fe392f13296e77 100644 (file)
@@ -102,8 +102,7 @@ static void ps3disk_scatter_gather(struct ps3_storage_device *dev,
                dev_dbg(&dev->sbd.core,
                        "%s:%u: bio %u: %u segs %u sectors from %lu\n",
                        __func__, __LINE__, i, bio_segments(iter.bio),
-                       bio_sectors(iter.bio),
-                       (unsigned long)iter.bio->bi_sector);
+                       bio_sectors(iter.bio), iter.bio->bi_sector);
 
                size = bvec->bv_len;
                buf = bvec_kmap_irq(bvec, &flags);
@@ -406,7 +405,6 @@ static void ps3disk_prepare_flush(struct request_queue *q, struct request *req)
 
        dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
 
-       memset(req->cmd, 0, sizeof(req->cmd));
        req->cmd_type = REQ_TYPE_FLUSH;
 }
 
index 27bfe72aab59360951b133b0be25c88ba85ea6c4..e322cce8c12d7870d45b2b202c8ff60e9e924c9f 100644 (file)
@@ -2399,7 +2399,7 @@ static void ub_disconnect(struct usb_interface *intf)
                del_gendisk(lun->disk);
                /*
                 * I wish I could do:
-                *    set_bit(QUEUE_FLAG_DEAD, &q->queue_flags);
+                *    queue_flag_set(QUEUE_FLAG_DEAD, q);
                 * As it is, we rely on our internal poisoning and let
                 * the upper levels to spin furiously failing all the I/O.
                 */
index d771da816d95d708cff253e41e3a6ab05cd9d930..f2fff5799ddf0fe1b41909b64d606d747f9081f7 100644 (file)
@@ -137,7 +137,7 @@ static void blkif_restart_queue_callback(void *arg)
        schedule_work(&info->work);
 }
 
-int blkif_getgeo(struct block_device *bd, struct hd_geometry *hg)
+static int blkif_getgeo(struct block_device *bd, struct hd_geometry *hg)
 {
        /* We don't have real geometry info, but let's at least return
           values consistent with the size of the device */
index 7e31d5f1bc8aa41444821da3b6c4d34b82fe96b8..e5cd856a2fea9cce67404059f0e52d8a82ac5d2c 100644 (file)
@@ -143,7 +143,7 @@ restart:
                int len;
 
                set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
-               len = tty->driver->write(tty, skb->data, skb->len);
+               len = tty->ops->write(tty, skb->data, skb->len);
                hdev->stat.byte_tx += len;
 
                skb_pull(skb, len);
@@ -190,8 +190,7 @@ static int hci_uart_flush(struct hci_dev *hdev)
 
        /* Flush any pending characters in the driver and discipline. */
        tty_ldisc_flush(tty);
-       if (tty->driver && tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       tty_driver_flush_buffer(tty);
 
        if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
                hu->proto->flush(hu);
@@ -285,9 +284,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
 
        if (tty->ldisc.flush_buffer)
                tty->ldisc.flush_buffer(tty);
-
-       if (tty->driver && tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       tty_driver_flush_buffer(tty);
 
        return 0;
 }
@@ -373,9 +370,7 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *f
        hu->hdev->stat.byte_rx += count;
        spin_unlock(&hu->rx_lock);
 
-       if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
-                                       tty->driver->unthrottle)
-               tty->driver->unthrottle(tty);
+       tty_unthrottle(tty);
 }
 
 static int hci_uart_register_dev(struct hci_uart *hu)
index ac3829030ac581bca1475b9f345e4f7a3f7e7f85..69f26eb6415bdbb9824ed89ca1307134fe55b647 100644 (file)
@@ -2194,7 +2194,6 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
                if (ret)
                        break;
 
-               memset(rq->cmd, 0, sizeof(rq->cmd));
                rq->cmd[0] = GPCMD_READ_CD;
                rq->cmd[1] = 1 << 2;
                rq->cmd[2] = (lba >> 24) & 0xff;
index b74b6c2768a8fbcd15d0468dc33fbe450e843609..5245a4a0ba74c4d1d0fb0debd89c0296f43a39b3 100644 (file)
@@ -144,6 +144,7 @@ static int proc_viocd_open(struct inode *inode, struct file *file)
 }
 
 static const struct file_operations proc_viocd_operations = {
+       .owner          = THIS_MODULE,
        .open           = proc_viocd_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -679,7 +680,6 @@ static struct vio_driver viocd_driver = {
 
 static int __init viocd_init(void)
 {
-       struct proc_dir_entry *e;
        int ret = 0;
 
        if (!firmware_has_feature(FW_FEATURE_ISERIES))
@@ -719,12 +719,8 @@ static int __init viocd_init(void)
        if (ret)
                goto out_free_info;
 
-       e = create_proc_entry("iSeries/viocd", S_IFREG|S_IRUGO, NULL);
-       if (e) {
-               e->owner = THIS_MODULE;
-               e->proc_fops = &proc_viocd_operations;
-       }
-
+       proc_create("iSeries/viocd", S_IFREG|S_IRUGO, NULL,
+                   &proc_viocd_operations);
        return 0;
 
 out_free_info:
index 929d4fa73fd97239457313d5be14cf462168a4b0..5dce3877eee589f8bd680a7c3df8eab74cdd4888 100644 (file)
@@ -80,6 +80,15 @@ config VT_HW_CONSOLE_BINDING
         information. For framebuffer console users, please refer to
         <file:Documentation/fb/fbcon.txt>.
 
+config DEVKMEM
+       bool "/dev/kmem virtual device support"
+       default y
+       help
+         Say Y here if you want to support the /dev/kmem device. The
+         /dev/kmem device is rarely used, but can be used for certain
+         kind of kernel debugging operations.
+         When in doubt, say "N".
+
 config SERIAL_NONSTANDARD
        bool "Non-standard serial port support"
        depends on HAS_IOMEM
index c69f79598e47cb4c9e375bc648daaa0e28e26646..99e6a406efb436b8269fe5a57cfe5971400bbdf2 100644 (file)
@@ -35,7 +35,7 @@
 
 //#define AGP_DEBUG 1
 #ifdef AGP_DEBUG
-#define DBG(x,y...) printk (KERN_DEBUG PFX "%s: " x "\n", __FUNCTION__ , ## y)
+#define DBG(x,y...) printk (KERN_DEBUG PFX "%s: " x "\n", __func__ , ## y)
 #else
 #define DBG(x,y...) do { } while (0)
 #endif
index 3d468f502d2db021cc99007784ecf14fa59c6526..37457e5a4f2b8ce6d06f728788dbeee2a54e3fee 100644 (file)
@@ -832,33 +832,34 @@ static void change_speed(struct async_struct *info,
        local_irq_restore(flags);
 }
 
-static void rs_put_char(struct tty_struct *tty, unsigned char ch)
+static int rs_put_char(struct tty_struct *tty, unsigned char ch)
 {
        struct async_struct *info;
        unsigned long flags;
 
        if (!tty)
-               return;
+               return 0;
 
        info = tty->driver_data;
 
        if (serial_paranoia_check(info, tty->name, "rs_put_char"))
-               return;
+               return 0;
 
        if (!info->xmit.buf)
-               return;
+               return 0;
 
        local_irq_save(flags);
        if (CIRC_SPACE(info->xmit.head,
                       info->xmit.tail,
                       SERIAL_XMIT_SIZE) == 0) {
                local_irq_restore(flags);
-               return;
+               return 0;
        }
 
        info->xmit.buf[info->xmit.head++] = ch;
        info->xmit.head &= SERIAL_XMIT_SIZE-1;
        local_irq_restore(flags);
+       return 1;
 }
 
 static void rs_flush_chars(struct tty_struct *tty)
@@ -1074,6 +1075,7 @@ static int get_serial_info(struct async_struct * info,
        if (!retinfo)
                return -EFAULT;
        memset(&tmp, 0, sizeof(tmp));
+       lock_kernel();
        tmp.type = state->type;
        tmp.line = state->line;
        tmp.port = state->port;
@@ -1084,6 +1086,7 @@ static int get_serial_info(struct async_struct * info,
        tmp.close_delay = state->close_delay;
        tmp.closing_wait = state->closing_wait;
        tmp.custom_divisor = state->custom_divisor;
+       unlock_kernel();
        if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
                return -EFAULT;
        return 0;
@@ -1099,13 +1102,17 @@ static int set_serial_info(struct async_struct * info,
 
        if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
                return -EFAULT;
+
+       lock_kernel();
        state = info->state;
        old_state = *state;
   
        change_irq = new_serial.irq != state->irq;
        change_port = (new_serial.port != state->port);
-       if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size))
+       if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) {
+         unlock_kernel();
          return -EINVAL;
+       }
   
        if (!serial_isroot()) {
                if ((new_serial.baud_base != state->baud_base) ||
@@ -1122,8 +1129,10 @@ static int set_serial_info(struct async_struct * info,
                goto check_and_exit;
        }
 
-       if (new_serial.baud_base < 9600)
+       if (new_serial.baud_base < 9600) {
+               unlock_kernel();
                return -EINVAL;
+       }
 
        /*
         * OK, past this point, all the error checking has been done.
@@ -1157,6 +1166,7 @@ check_and_exit:
                }
        } else
                retval = startup(info);
+       unlock_kernel();
        return retval;
 }
 
@@ -1496,8 +1506,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
                rs_wait_until_sent(tty, info->timeout);
        }
        shutdown(info);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       rs_flush_buffer(tty);
                
        tty_ldisc_flush(tty);
        tty->closing = 0;
@@ -1530,6 +1539,8 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
                return; /* Just in case.... */
 
        orig_jiffies = jiffies;
+
+       lock_kernel();
        /*
         * Set the check interval to be 1/5 of the estimated time to
         * send a single character, and make it at least 1.  The check
@@ -1570,6 +1581,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
                        break;
        }
        __set_current_state(TASK_RUNNING);
+       unlock_kernel();
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
        printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
 #endif
index 17d54315e146e5d95b794f456a270e2e818b08c6..cdd876dbb2b0f77ab05e27c37f0671724743537c 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/poll.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/miscdevice.h>
 #include <linux/apm_bios.h>
 #include <linux/capability.h>
@@ -493,11 +494,10 @@ static struct miscdevice apm_device = {
  *     -1: Unknown
  *   8) min = minutes; sec = seconds
  */
-static int apm_get_info(char *buf, char **start, off_t fpos, int length)
+static int proc_apm_show(struct seq_file *m, void *v)
 {
        struct apm_power_info info;
        char *units;
-       int ret;
 
        info.ac_line_status = 0xff;
        info.battery_status = 0xff;
@@ -515,14 +515,27 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
        case 1:         units = "sec";  break;
        }
 
-       ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
+       seq_printf(m, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
                     driver_version, APM_32_BIT_SUPPORT,
                     info.ac_line_status, info.battery_status,
                     info.battery_flag, info.battery_life,
                     info.time, units);
 
-       return ret;
+       return 0;
 }
+
+static int proc_apm_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, proc_apm_show, NULL);
+}
+
+static const struct file_operations apm_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = proc_apm_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
 #endif
 
 static int kapmd(void *arg)
@@ -593,7 +606,7 @@ static int __init apm_init(void)
        wake_up_process(kapmd_tsk);
 
 #ifdef CONFIG_PROC_FS
-       create_proc_info_entry("apm", 0, NULL, apm_get_info);
+       proc_create("apm", 0, NULL, &apm_proc_fops);
 #endif
 
        ret = misc_register(&apm_device);
index a7c4990b5b6bf0f3929bad97d5957aad0e134ce6..31d08b641f5be84667c5d53e49c862915e65d0c8 100644 (file)
@@ -199,7 +199,7 @@ static int __init applicom_init(void)
                if (pci_enable_device(dev))
                        return -EIO;
 
-               RamIO = ioremap(pci_resource_start(dev, 0), LEN_RAM_IO);
+               RamIO = ioremap_nocache(pci_resource_start(dev, 0), LEN_RAM_IO);
 
                if (!RamIO) {
                        printk(KERN_INFO "ac.o: Failed to ioremap PCI memory "
@@ -254,7 +254,7 @@ static int __init applicom_init(void)
        /* Now try the specified ISA cards */
 
        for (i = 0; i < MAX_ISA_BOARD; i++) {
-               RamIO = ioremap(mem + (LEN_RAM_IO * i), LEN_RAM_IO);
+               RamIO = ioremap_nocache(mem + (LEN_RAM_IO * i), LEN_RAM_IO);
 
                if (!RamIO) {
                        printk(KERN_INFO "ac.o: Failed to ioremap the ISA card's memory space (slot #%d)\n", i + 1);
index 6b104e45a322b3a5bd321a07f12a4c3936441db6..4246b8e36cb32853eedb658b3e96f3c4a46ba978 100644 (file)
@@ -277,6 +277,7 @@ u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
                        return p->inverse_translations[m][glyph];
        }
 }
+EXPORT_SYMBOL_GPL(inverse_translate);
 
 static void update_user_maps(void)
 {
index e4f579c3e2455640a3d1dc27c742e20d26ea2c01..ef73e72daedcf978197c062d181a41de86b465d6 100644 (file)
@@ -21,7 +21,6 @@
  *
  * This version supports shared IRQ's (only for PCI boards).
  *
- * $Log: cyclades.c,v $
  * Prevent users from opening non-existing Z ports.
  *
  * Revision 2.3.2.8   2000/07/06 18:14:16 ivan
@@ -62,7 +61,7 @@
  * Driver now makes sure that the constant SERIAL_XMIT_SIZE is defined;
  *
  * Revision 2.3.2.2   1999/10/01 11:27:43 ivan
- * Fixed bug in cyz_poll that would make all ports but port 0 
+ * Fixed bug in cyz_poll that would make all ports but port 0
  * unable to transmit/receive data (Cyclades-Z only);
  * Implemented logic to prevent the RX buffer from being stuck with data
  * due to a driver / firmware race condition in interrupt op mode
  * Revision 2.3.1.1   1999/07/15 16:45:53 ivan
  * Removed CY_PROC conditional compilation;
  * Implemented SMP-awareness for the driver;
- * Implemented a new ISA IRQ autoprobe that uses the irq_probe_[on|off] 
+ * Implemented a new ISA IRQ autoprobe that uses the irq_probe_[on|off]
  * functions;
  * The driver now accepts memory addresses (maddr=0xMMMMM) and IRQs
  * (irq=NN) as parameters (only for ISA boards);
- * Fixed bug in set_line_char that would prevent the Cyclades-Z 
+ * Fixed bug in set_line_char that would prevent the Cyclades-Z
  * ports from being configured at speeds above 115.2Kbps;
  * Fixed bug in cy_set_termios that would prevent XON/XOFF flow control
  * switching from working properly;
- * The driver now only prints IRQ info for the Cyclades-Z if it's 
+ * The driver now only prints IRQ info for the Cyclades-Z if it's
  * configured to work in interrupt mode;
  *
  * Revision 2.2.2.3   1999/06/28 11:13:29 ivan
  * Added support for interrupt mode operation for the Z cards;
  * Removed the driver inactivity control for the Z;
- * Added a missing MOD_DEC_USE_COUNT in the cy_open function for when 
+ * Added a missing MOD_DEC_USE_COUNT in the cy_open function for when
  * the Z firmware is not loaded yet;
- * Replaced the "manual" Z Tx flush buffer by a call to a FW command of 
+ * Replaced the "manual" Z Tx flush buffer by a call to a FW command of
  * same functionality;
- * Implemented workaround for IRQ setting loss on the PCI configuration 
+ * Implemented workaround for IRQ setting loss on the PCI configuration
  * registers after a PCI bridge EEPROM reload (affects PLX9060 only);
  *
  * Revision 2.2.2.2  1999/05/14 17:18:15 ivan
  * BREAK implementation changed in order to make use of the 'break_ctl'
  * TTY facility;
  * Fixed typo in TTY structure field 'driver_name';
- * Included a PCI bridge reset and EEPROM reload in the board 
+ * Included a PCI bridge reset and EEPROM reload in the board
  * initialization code (for both Y and Z series).
  *
  * Revision 2.2.2.1  1999/04/08 16:17:43 ivan
- * Fixed a bug in cy_wait_until_sent that was preventing the port to be 
+ * Fixed a bug in cy_wait_until_sent that was preventing the port to be
  * closed properly after a SIGINT;
  * Module usage counter scheme revisited;
  * Added support to the upcoming Y PCI boards (i.e., support to additional
  * PCI Device ID's).
- * 
+ *
  * Revision 2.2.1.10 1999/01/20 16:14:29 ivan
  * Removed all unnecessary page-alignement operations in ioremap calls
  * (ioremap is currently safe for these operations).
  *
  * Revision 2.2.1.9  1998/12/30 18:18:30 ivan
- * Changed access to PLX PCI bridge registers from I/O to MMIO, in 
+ * Changed access to PLX PCI bridge registers from I/O to MMIO, in
  * order to make PLX9050-based boards work with certain motherboards.
  *
  * Revision 2.2.1.8  1998/11/13 12:46:20 ivan
  * Fixed Cyclom-4Yo hardware detection bug.
  *
  * Revision 2.2.1.4  1998/08/04 11:02:50 ivan
- * /proc/cyclades implementation with great collaboration of 
+ * /proc/cyclades implementation with great collaboration of
  * Marc Lewis <marc@blarg.net>;
  * cyy_interrupt was changed to avoid occurrence of kernel oopses
  * during PPP operation.
  * General code review in order to comply with 2.1 kernel standards;
  * data loss prevention for slow devices revisited (cy_wait_until_sent
  * was created);
- * removed conditional compilation for new/old PCI structure support 
+ * removed conditional compilation for new/old PCI structure support
  * (now the driver only supports the new PCI structure).
  *
  * Revision 2.2.1.1  1998/03/19 16:43:12 ivan
  * cleaned up the data loss fix;
  * fixed XON/XOFF handling once more (Cyclades-Z);
  * general review of the driver routines;
- * introduction of a mechanism to prevent data loss with slow 
+ * introduction of a mechanism to prevent data loss with slow
  * printers, by forcing a delay before closing the port.
  *
  * Revision 2.1.1.2  1998/02/17 16:50:00 ivan
  * Code review for the module cleanup routine;
  * fixed RTS and DTR status report for new CD1400's in get_modem_info;
  * includes anonymous changes regarding signal_pending.
- * 
+ *
  * Revision 2.1  1997/11/01 17:42:41 ivan
  * Changes in the driver to support Alpha systems (except 8Zo V_1);
  * BREAK fix for the Cyclades-Z boards;
  * driver inactivity control by FW implemented;
- * introduction of flag that allows driver to take advantage of 
+ * introduction of flag that allows driver to take advantage of
  * a special CD1400 feature related to HW flow control;
  * added support for the CD1400  rev. J (Cyclom-Y boards);
  * introduction of ioctls to:
  *  - adjust the polling interval (Cyclades-Z);
  *
  * Revision 1.36.4.33  1997/06/27 19:00:00  ivan
- * Fixes related to kernel version conditional 
+ * Fixes related to kernel version conditional
  * compilation.
- *  
+ *
  * Revision 1.36.4.32  1997/06/14 19:30:00  ivan
- * Compatibility issues between kernels 2.0.x and 
+ * Compatibility issues between kernels 2.0.x and
  * 2.1.x (mainly related to clear_bit function).
- *  
+ *
  * Revision 1.36.4.31  1997/06/03 15:30:00  ivan
- * Changes to define the memory window according to the 
+ * Changes to define the memory window according to the
  * board type.
- *  
+ *
  * Revision 1.36.4.30  1997/05/16 15:30:00  daniel
  * Changes to support new cycladesZ boards.
  *
 #undef CY_PCI_DEBUG
 
 /*
- * Include section 
+ * Include section
  */
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/firmware.h>
 
 #include <asm/system.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -668,10 +667,10 @@ static void cy_send_xchar(struct tty_struct *tty, char ch);
        ((readl(&((struct RUNTIME_9060 __iomem *) \
                ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0)
 
-#define ISZLOADED(card)        (((ZO_V1==readl(&((struct RUNTIME_9060 __iomem *) \
+#define ISZLOADED(card)        (((ZO_V1 == readl(&((struct RUNTIME_9060 __iomem *) \
                        ((card).ctl_addr))->mail_box_0)) || \
                        Z_FPGA_CHECK(card)) && \
-                       (ZFIRM_ID==readl(&((struct FIRM_ID __iomem *) \
+                       (ZFIRM_ID == readl(&((struct FIRM_ID __iomem *) \
                        ((card).base_addr+ID_ADDRESS))->signature)))
 
 #ifndef SERIAL_XMIT_SIZE
@@ -809,12 +808,12 @@ static char baud_cor3[] = {       /* receive threshold */
 
 /*
  * The Cyclades driver implements HW flow control as any serial driver.
- * The cyclades_port structure member rflow and the vector rflow_thr 
- * allows us to take advantage of a special feature in the CD1400 to avoid 
- * data loss even when the system interrupt latency is too high. These flags 
- * are to be used only with very special applications. Setting these flags 
- * requires the use of a special cable (DTR and RTS reversed). In the new 
- * CD1400-based boards (rev. 6.00 or later), there is no need for special 
+ * The cyclades_port structure member rflow and the vector rflow_thr
+ * allows us to take advantage of a special feature in the CD1400 to avoid
+ * data loss even when the system interrupt latency is too high. These flags
+ * are to be used only with very special applications. Setting these flags
+ * requires the use of a special cable (DTR and RTS reversed). In the new
+ * CD1400-based boards (rev. 6.00 or later), there is no need for special
  * cables.
  */
 
@@ -841,14 +840,22 @@ static int cy_chip_offset[] = { 0x0000,
 
 #ifdef CONFIG_PCI
 static struct pci_device_id cy_pci_dev_id[] __devinitdata = {
-       { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) },      /* PCI < 1Mb */
-       { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Hi) },      /* PCI > 1Mb */
-       { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Lo) },     /* 4Y PCI < 1Mb */
-       { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Hi) },     /* 4Y PCI > 1Mb */
-       { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Lo) },     /* 8Y PCI < 1Mb */
-       { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Hi) },     /* 8Y PCI > 1Mb */
-       { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Lo) },      /* Z PCI < 1Mb */
-       { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Hi) },      /* Z PCI > 1Mb */
+       /* PCI < 1Mb */
+       { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) },
+       /* PCI > 1Mb */
+       { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Hi) },
+       /* 4Y PCI < 1Mb */
+       { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Lo) },
+       /* 4Y PCI > 1Mb */
+       { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Hi) },
+       /* 8Y PCI < 1Mb */
+       { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Lo) },
+       /* 8Y PCI > 1Mb */
+       { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Hi) },
+       /* Z PCI < 1Mb */
+       { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Lo) },
+       /* Z PCI > 1Mb */
+       { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Hi) },
        { }                     /* end of table */
 };
 MODULE_DEVICE_TABLE(pci, cy_pci_dev_id);
@@ -905,15 +912,14 @@ static inline int serial_paranoia_check(struct cyclades_port *info,
 
    This function is only called from inside spinlock-protected code.
  */
-static int cyy_issue_cmd(void __iomem * base_addr, u_char cmd, int index)
+static int cyy_issue_cmd(void __iomem *base_addr, u_char cmd, int index)
 {
        unsigned int i;
 
        /* Check to see that the previous command has completed */
        for (i = 0; i < 100; i++) {
-               if (readb(base_addr + (CyCCR << index)) == 0) {
+               if (readb(base_addr + (CyCCR << index)) == 0)
                        break;
-               }
                udelay(10L);
        }
        /* if the CCR never cleared, the previous command
@@ -929,7 +935,7 @@ static int cyy_issue_cmd(void __iomem * base_addr, u_char cmd, int index)
 
 #ifdef CONFIG_ISA
 /* ISA interrupt detection code */
-static unsigned detect_isa_irq(void __iomem * address)
+static unsigned detect_isa_irq(void __iomem *address)
 {
        int irq;
        unsigned long irqs, flags;
@@ -1038,7 +1044,7 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
                                        if (info->flags & ASYNC_SAK)
                                                do_SAK(tty);
                                } else if (data & CyFRAME) {
-                                       tty_insert_flip_char( tty,
+                                       tty_insert_flip_char(tty,
                                                readb(base_addr + (CyRDSR <<
                                                        index)), TTY_FRAME);
                                        info->icount.rx++;
@@ -1320,7 +1326,8 @@ static irqreturn_t cyy_interrupt(int irq, void *dev_id)
 
        if (unlikely(cinfo == NULL)) {
 #ifdef CY_DEBUG_INTERRUPTS
-               printk(KERN_DEBUG "cyy_interrupt: spurious interrupt %d\n",irq);
+               printk(KERN_DEBUG "cyy_interrupt: spurious interrupt %d\n",
+                               irq);
 #endif
                return IRQ_NONE;        /* spurious interrupt */
        }
@@ -1375,12 +1382,12 @@ static irqreturn_t cyy_interrupt(int irq, void *dev_id)
 
 /***********************************************************/
 /********* End of block of Cyclom-Y specific code **********/
-/******** Start of block of Cyclades-Z specific code *********/
+/******** Start of block of Cyclades-Z specific code *******/
 /***********************************************************/
 
 static int
 cyz_fetch_msg(struct cyclades_card *cinfo,
-               __u32 * channel, __u8 * cmd, __u32 * param)
+               __u32 *channel, __u8 *cmd, __u32 *param)
 {
        struct FIRM_ID __iomem *firm_id;
        struct ZFW_CTRL __iomem *zfw_ctrl;
@@ -1388,9 +1395,8 @@ cyz_fetch_msg(struct cyclades_card *cinfo,
        unsigned long loc_doorbell;
 
        firm_id = cinfo->base_addr + ID_ADDRESS;
-       if (!ISZLOADED(*cinfo)) {
+       if (!ISZLOADED(*cinfo))
                return -1;
-       }
        zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
        board_ctrl = &zfw_ctrl->board_ctrl;
 
@@ -1418,9 +1424,9 @@ cyz_issue_cmd(struct cyclades_card *cinfo,
        unsigned int index;
 
        firm_id = cinfo->base_addr + ID_ADDRESS;
-       if (!ISZLOADED(*cinfo)) {
+       if (!ISZLOADED(*cinfo))
                return -1;
-       }
+
        zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
        board_ctrl = &zfw_ctrl->board_ctrl;
 
@@ -1428,9 +1434,8 @@ cyz_issue_cmd(struct cyclades_card *cinfo,
        pci_doorbell =
            &((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->pci_doorbell;
        while ((readl(pci_doorbell) & 0xff) != 0) {
-               if (index++ == 1000) {
+               if (index++ == 1000)
                        return (int)(readl(pci_doorbell) & 0xff);
-               }
                udelay(50L);
        }
        cy_writel(&board_ctrl->hcmd_channel, channel);
@@ -1504,7 +1509,8 @@ static void cyz_handle_rx(struct cyclades_port *info,
                        while (len--) {
                                data = readb(cinfo->base_addr + rx_bufaddr +
                                                new_rx_get);
-                               new_rx_get = (new_rx_get + 1)& (rx_bufsize - 1);
+                               new_rx_get = (new_rx_get + 1) &
+                                                       (rx_bufsize - 1);
                                tty_insert_flip_char(tty, data, TTY_NORMAL);
                                info->idle_stats.recv_bytes++;
                                info->icount.rx++;
@@ -1636,7 +1642,8 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
                special_count = 0;
                delta_count = 0;
                info = &cinfo->ports[channel];
-               if ((tty = info->tty) == NULL)
+               tty = info->tty;
+               if (tty == NULL)
                        continue;
 
                ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
@@ -1732,7 +1739,8 @@ static irqreturn_t cyz_interrupt(int irq, void *dev_id)
 
        if (unlikely(cinfo == NULL)) {
 #ifdef CY_DEBUG_INTERRUPTS
-               printk(KERN_DEBUG "cyz_interrupt: spurious interrupt %d\n",irq);
+               printk(KERN_DEBUG "cyz_interrupt: spurious interrupt %d\n",
+                                                                       irq);
 #endif
                return IRQ_NONE;        /* spurious interrupt */
        }
@@ -1851,9 +1859,8 @@ static int startup(struct cyclades_port *info)
        }
 
        if (!info->type) {
-               if (info->tty) {
+               if (info->tty)
                        set_bit(TTY_IO_ERROR, &info->tty->flags);
-               }
                free_page(page);
                goto errout;
        }
@@ -1904,9 +1911,8 @@ static int startup(struct cyclades_port *info)
                        readb(base_addr + (CySRER << index)) | CyRxData);
                info->flags |= ASYNC_INITIALIZED;
 
-               if (info->tty) {
+               if (info->tty)
                        clear_bit(TTY_IO_ERROR, &info->tty->flags);
-               }
                info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
                info->breakon = info->breakoff = 0;
                memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
@@ -1925,9 +1931,8 @@ static int startup(struct cyclades_port *info)
                base_addr = card->base_addr;
 
                firm_id = base_addr + ID_ADDRESS;
-               if (!ISZLOADED(*card)) {
+               if (!ISZLOADED(*card))
                        return -ENODEV;
-               }
 
                zfw_ctrl = card->base_addr +
                                (readl(&firm_id->zfwctrl_addr) & 0xfffff);
@@ -1990,9 +1995,8 @@ static int startup(struct cyclades_port *info)
                /* enable send, recv, modem !!! */
 
                info->flags |= ASYNC_INITIALIZED;
-               if (info->tty) {
+               if (info->tty)
                        clear_bit(TTY_IO_ERROR, &info->tty->flags);
-               }
                info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
                info->breakon = info->breakoff = 0;
                memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
@@ -2061,9 +2065,8 @@ static void shutdown(struct cyclades_port *info)
        void __iomem *base_addr;
        int chip, channel, index;
 
-       if (!(info->flags & ASYNC_INITIALIZED)) {
+       if (!(info->flags & ASYNC_INITIALIZED))
                return;
-       }
 
        card = info->card;
        channel = info->line - card->first_line;
@@ -2105,9 +2108,8 @@ static void shutdown(struct cyclades_port *info)
                /* it may be appropriate to clear _XMIT at
                   some later date (after testing)!!! */
 
-               if (info->tty) {
+               if (info->tty)
                        set_bit(TTY_IO_ERROR, &info->tty->flags);
-               }
                info->flags &= ~ASYNC_INITIALIZED;
                spin_unlock_irqrestore(&card->card_lock, flags);
        } else {
@@ -2124,9 +2126,8 @@ static void shutdown(struct cyclades_port *info)
 #endif
 
                firm_id = base_addr + ID_ADDRESS;
-               if (!ISZLOADED(*card)) {
+               if (!ISZLOADED(*card))
                        return;
-               }
 
                zfw_ctrl = card->base_addr +
                                (readl(&firm_id->zfwctrl_addr) & 0xfffff);
@@ -2157,9 +2158,8 @@ static void shutdown(struct cyclades_port *info)
 #endif
                }
 
-               if (info->tty) {
+               if (info->tty)
                        set_bit(TTY_IO_ERROR, &info->tty->flags);
-               }
                info->flags &= ~ASYNC_INITIALIZED;
 
                spin_unlock_irqrestore(&card->card_lock, flags);
@@ -2204,7 +2204,8 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
         * If non-blocking mode is set, then make the check up front
         * and then exit.
         */
-       if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
+       if ((filp->f_flags & O_NONBLOCK) ||
+                                       (tty->flags & (1 << TTY_IO_ERROR))) {
                info->flags |= ASYNC_NORMAL_ACTIVE;
                return 0;
        }
@@ -2301,7 +2302,8 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
                        return -EINVAL;
                }
 
-               zfw_ctrl = base_addr + (readl(&firm_id->zfwctrl_addr)& 0xfffff);
+               zfw_ctrl = base_addr + (readl(&firm_id->zfwctrl_addr)
+                                                               & 0xfffff);
                board_ctrl = &zfw_ctrl->board_ctrl;
                ch_ctrl = zfw_ctrl->ch_ctrl;
 
@@ -2378,9 +2380,9 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
        int retval;
 
        line = tty->index;
-       if ((tty->index < 0) || (NR_PORTS <= line)) {
+       if (tty->index < 0 || NR_PORTS <= line)
                return -ENODEV;
-       }
+
        for (i = 0; i < NR_CARDS; i++)
                if (line < cy_card[i].first_line + cy_card[i].nports &&
                                line >= cy_card[i].first_line)
@@ -2388,9 +2390,8 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
        if (i >= NR_CARDS)
                return -ENODEV;
        info = &cy_card[i].ports[line - cy_card[i].first_line];
-       if (info->line < 0) {
+       if (info->line < 0)
                return -ENODEV;
-       }
 
        /* If the card's firmware hasn't been loaded,
           treat it as absent from the system.  This
@@ -2456,9 +2457,9 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
 #endif
        tty->driver_data = info;
        info->tty = tty;
-       if (serial_paranoia_check(info, tty->name, "cy_open")) {
+       if (serial_paranoia_check(info, tty->name, "cy_open"))
                return -ENODEV;
-       }
+
 #ifdef CY_DEBUG_OPEN
        printk(KERN_DEBUG "cyc:cy_open ttyC%d, count = %d\n", info->line,
                        info->count);
@@ -2482,9 +2483,8 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
         * Start up serial port
         */
        retval = startup(info);
-       if (retval) {
+       if (retval)
                return retval;
-       }
 
        retval = block_til_ready(tty, filp, info);
        if (retval) {
@@ -2522,6 +2522,7 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
                return;         /* Just in case.... */
 
        orig_jiffies = jiffies;
+       lock_kernel();
        /*
         * Set the check interval to be 1/5 of the estimated time to
         * send a single character, and make it at least 1.  The check
@@ -2573,11 +2574,47 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
        }
        /* Run one more char cycle */
        msleep_interruptible(jiffies_to_msecs(char_time * 5));
+       unlock_kernel();
 #ifdef CY_DEBUG_WAIT_UNTIL_SENT
        printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies);
 #endif
 }
 
+static void cy_flush_buffer(struct tty_struct *tty)
+{
+       struct cyclades_port *info = tty->driver_data;
+       struct cyclades_card *card;
+       int channel, retval;
+       unsigned long flags;
+
+#ifdef CY_DEBUG_IO
+       printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line);
+#endif
+
+       if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
+               return;
+
+       card = info->card;
+       channel = info->line - card->first_line;
+
+       spin_lock_irqsave(&card->card_lock, flags);
+       info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+       spin_unlock_irqrestore(&card->card_lock, flags);
+
+       if (IS_CYC_Z(*card)) {  /* If it is a Z card, flush the on-board
+                                          buffers as well */
+               spin_lock_irqsave(&card->card_lock, flags);
+               retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L);
+               if (retval != 0) {
+                       printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d "
+                               "was %x\n", info->line, retval);
+               }
+               spin_unlock_irqrestore(&card->card_lock, flags);
+       }
+       tty_wakeup(tty);
+}                              /* cy_flush_buffer */
+
+
 /*
  * This routine is called when a particular tty device is closed.
  */
@@ -2591,9 +2628,8 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
        printk(KERN_DEBUG "cyc:cy_close ttyC%d\n", info->line);
 #endif
 
-       if (!info || serial_paranoia_check(info, tty->name, "cy_close")) {
+       if (!info || serial_paranoia_check(info, tty->name, "cy_close"))
                return;
-       }
 
        card = info->card;
 
@@ -2641,9 +2677,9 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
         */
        tty->closing = 1;
        spin_unlock_irqrestore(&card->card_lock, flags);
-       if (info->closing_wait != CY_CLOSING_WAIT_NONE) {
+       if (info->closing_wait != CY_CLOSING_WAIT_NONE)
                tty_wait_until_sent(tty, info->closing_wait);
-       }
+
        spin_lock_irqsave(&card->card_lock, flags);
 
        if (!IS_CYC_Z(*card)) {
@@ -2657,15 +2693,16 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
                cy_writeb(base_addr + (CySRER << index),
                          readb(base_addr + (CySRER << index)) & ~CyRxData);
                if (info->flags & ASYNC_INITIALIZED) {
-                       /* Waiting for on-board buffers to be empty before closing
-                          the port */
+                       /* Waiting for on-board buffers to be empty before
+                          closing the port */
                        spin_unlock_irqrestore(&card->card_lock, flags);
                        cy_wait_until_sent(tty, info->timeout);
                        spin_lock_irqsave(&card->card_lock, flags);
                }
        } else {
 #ifdef Z_WAKE
-               /* Waiting for on-board buffers to be empty before closing the port */
+               /* Waiting for on-board buffers to be empty before closing
+                  the port */
                void __iomem *base_addr = card->base_addr;
                struct FIRM_ID __iomem *firm_id = base_addr + ID_ADDRESS;
                struct ZFW_CTRL __iomem *zfw_ctrl =
@@ -2689,8 +2726,7 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
 
        spin_unlock_irqrestore(&card->card_lock, flags);
        shutdown(info);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       cy_flush_buffer(tty);
        tty_ldisc_flush(tty);
        spin_lock_irqsave(&card->card_lock, flags);
 
@@ -2738,17 +2774,16 @@ static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
        printk(KERN_DEBUG "cyc:cy_write ttyC%d\n", info->line);
 #endif
 
-       if (serial_paranoia_check(info, tty->name, "cy_write")) {
+       if (serial_paranoia_check(info, tty->name, "cy_write"))
                return 0;
-       }
 
        if (!info->xmit_buf)
                return 0;
 
        spin_lock_irqsave(&info->card->card_lock, flags);
        while (1) {
-               c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1),
-                                  (int)(SERIAL_XMIT_SIZE - info->xmit_head)));
+               c = min(count, (int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1));
+               c = min(c, (int)(SERIAL_XMIT_SIZE - info->xmit_head));
 
                if (c <= 0)
                        break;
@@ -2766,9 +2801,9 @@ static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
        info->idle_stats.xmit_bytes += ret;
        info->idle_stats.xmit_idle = jiffies;
 
-       if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
+       if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped)
                start_xmit(info);
-       }
+
        return ret;
 }                              /* cy_write */
 
@@ -2779,7 +2814,7 @@ static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
  * done stuffing characters into the driver.  If there is no room
  * in the queue, the character is ignored.
  */
-static void cy_put_char(struct tty_struct *tty, unsigned char ch)
+static int cy_put_char(struct tty_struct *tty, unsigned char ch)
 {
        struct cyclades_port *info = tty->driver_data;
        unsigned long flags;
@@ -2789,15 +2824,15 @@ static void cy_put_char(struct tty_struct *tty, unsigned char ch)
 #endif
 
        if (serial_paranoia_check(info, tty->name, "cy_put_char"))
-               return;
+               return 0;
 
        if (!info->xmit_buf)
-               return;
+               return 0;
 
        spin_lock_irqsave(&info->card->card_lock, flags);
        if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) {
                spin_unlock_irqrestore(&info->card->card_lock, flags);
-               return;
+               return 0;
        }
 
        info->xmit_buf[info->xmit_head++] = ch;
@@ -2806,11 +2841,12 @@ static void cy_put_char(struct tty_struct *tty, unsigned char ch)
        info->idle_stats.xmit_bytes++;
        info->idle_stats.xmit_idle = jiffies;
        spin_unlock_irqrestore(&info->card->card_lock, flags);
+       return 1;
 }                              /* cy_put_char */
 
 /*
  * This routine is called by the kernel after it has written a
- * series of characters to the tty device using put_char().  
+ * series of characters to the tty device using put_char().
  */
 static void cy_flush_chars(struct tty_struct *tty)
 {
@@ -2882,6 +2918,7 @@ static int cy_chars_in_buffer(struct tty_struct *tty)
                int char_count;
                __u32 tx_put, tx_get, tx_bufsize;
 
+               lock_kernel();
                firm_id = card->base_addr + ID_ADDRESS;
                zfw_ctrl = card->base_addr +
                        (readl(&firm_id->zfwctrl_addr) & 0xfffff);
@@ -2899,6 +2936,7 @@ static int cy_chars_in_buffer(struct tty_struct *tty)
                printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
                        info->line, info->xmit_cnt + char_count);
 #endif
+               unlock_kernel();
                return info->xmit_cnt + char_count;
        }
 #endif                         /* Z_EXT_CHARS_IN_BUFFER */
@@ -2950,12 +2988,12 @@ static void set_line_char(struct cyclades_port *info)
        int baud, baud_rate = 0;
        int i;
 
-       if (!info->tty || !info->tty->termios) {
+       if (!info->tty || !info->tty->termios)
                return;
-       }
-       if (info->line == -1) {
+
+       if (info->line == -1)
                return;
-       }
+
        cflag = info->tty->termios->c_cflag;
        iflag = info->tty->termios->c_iflag;
 
@@ -2994,13 +3032,11 @@ static void set_line_char(struct cyclades_port *info)
                }
                /* find the baud index */
                for (i = 0; i < 20; i++) {
-                       if (baud == baud_table[i]) {
+                       if (baud == baud_table[i])
                                break;
-                       }
                }
-               if (i == 20) {
+               if (i == 20)
                        i = 19; /* CD1400_MAX_SPEED */
-               }
 
                if (baud == 38400 && (info->flags & ASYNC_SPD_MASK) ==
                                ASYNC_SPD_CUST) {
@@ -3059,18 +3095,16 @@ static void set_line_char(struct cyclades_port *info)
                        info->cor1 = Cy_8_BITS;
                        break;
                }
-               if (cflag & CSTOPB) {
+               if (cflag & CSTOPB)
                        info->cor1 |= Cy_2_STOP;
-               }
+
                if (cflag & PARENB) {
-                       if (cflag & PARODD) {
+                       if (cflag & PARODD)
                                info->cor1 |= CyPARITY_O;
-                       } else {
+                       else
                                info->cor1 |= CyPARITY_E;
-                       }
-               } else {
+               } else
                        info->cor1 |= CyPARITY_NONE;
-               }
 
                /* CTS flow control flag */
                if (cflag & CRTSCTS) {
@@ -3123,7 +3157,8 @@ static void set_line_char(struct cyclades_port *info)
                cyy_issue_cmd(base_addr, CyCOR_CHANGE | CyCOR1ch | CyCOR2ch |
                                CyCOR3ch, index);
 
-               cy_writeb(base_addr + (CyCAR << index), (u_char) channel);      /* !!! Is this needed? */
+               /* !!! Is this needed? */
+               cy_writeb(base_addr + (CyCAR << index), (u_char) channel);
                cy_writeb(base_addr + (CyRTPR << index),
                        (info->default_timeout ? info->default_timeout : 0x02));
                /* 10ms rx timeout */
@@ -3191,9 +3226,8 @@ static void set_line_char(struct cyclades_port *info)
 #endif
                }
 
-               if (info->tty) {
+               if (info->tty)
                        clear_bit(TTY_IO_ERROR, &info->tty->flags);
-               }
                spin_unlock_irqrestore(&card->card_lock, flags);
 
        } else {
@@ -3206,9 +3240,8 @@ static void set_line_char(struct cyclades_port *info)
                int retval;
 
                firm_id = card->base_addr + ID_ADDRESS;
-               if (!ISZLOADED(*card)) {
+               if (!ISZLOADED(*card))
                        return;
-               }
 
                zfw_ctrl = card->base_addr +
                        (readl(&firm_id->zfwctrl_addr) & 0xfffff);
@@ -3268,14 +3301,12 @@ static void set_line_char(struct cyclades_port *info)
                                  readl(&ch_ctrl->comm_data_l) | C_DL_1STOP);
                }
                if (cflag & PARENB) {
-                       if (cflag & PARODD) {
+                       if (cflag & PARODD)
                                cy_writel(&ch_ctrl->comm_parity, C_PR_ODD);
-                       } else {
+                       else
                                cy_writel(&ch_ctrl->comm_parity, C_PR_EVEN);
-                       }
-               } else {
+               } else
                        cy_writel(&ch_ctrl->comm_parity, C_PR_NONE);
-               }
 
                /* CTS flow control flag */
                if (cflag & CRTSCTS) {
@@ -3305,11 +3336,10 @@ static void set_line_char(struct cyclades_port *info)
                }
 
                /* CD sensitivity */
-               if (cflag & CLOCAL) {
+               if (cflag & CLOCAL)
                        info->flags &= ~ASYNC_CHECK_CD;
-               } else {
+               else
                        info->flags |= ASYNC_CHECK_CD;
-               }
 
                if (baud == 0) {        /* baud rate is zero, turn off line */
                        cy_writel(&ch_ctrl->rs_control,
@@ -3325,21 +3355,20 @@ static void set_line_char(struct cyclades_port *info)
 #endif
                }
 
-               retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM,0L);
+               retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
                if (retval != 0) {
                        printk(KERN_ERR "cyc:set_line_char(2) retval on ttyC%d "
                                "was %x\n", info->line, retval);
                }
 
-               if (info->tty) {
+               if (info->tty)
                        clear_bit(TTY_IO_ERROR, &info->tty->flags);
-               }
        }
 }                              /* set_line_char */
 
 static int
 get_serial_info(struct cyclades_port *info,
-               struct serial_struct __user * retinfo)
+               struct serial_struct __user *retinfo)
 {
        struct serial_struct tmp;
        struct cyclades_card *cinfo = info->card;
@@ -3363,7 +3392,7 @@ get_serial_info(struct cyclades_port *info,
 
 static int
 set_serial_info(struct cyclades_port *info,
-               struct serial_struct __user * new_info)
+               struct serial_struct __user *new_info)
 {
        struct serial_struct new_serial;
        struct cyclades_port old_info;
@@ -3417,7 +3446,7 @@ check_and_exit:
  *         transmit holding register is empty.  This functionality
  *         allows an RS485 driver to be written in user space.
  */
-static int get_lsr_info(struct cyclades_port *info, unsigned int __user * value)
+static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value)
 {
        struct cyclades_card *card;
        int chip, channel, index;
@@ -3461,9 +3490,11 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file)
        struct BOARD_CTRL __iomem *board_ctrl;
        struct CH_CTRL __iomem *ch_ctrl;
 
-       if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+       if (serial_paranoia_check(info, tty->name, __func__))
                return -ENODEV;
 
+       lock_kernel();
+
        card = info->card;
        channel = info->line - card->first_line;
        if (!IS_CYC_Z(*card)) {
@@ -3506,10 +3537,12 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file)
                                ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0);
                } else {
                        result = 0;
+                       unlock_kernel();
                        return -ENODEV;
                }
 
        }
+       unlock_kernel();
        return result;
 }                              /* cy_tiomget */
 
@@ -3528,7 +3561,7 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
        struct CH_CTRL __iomem *ch_ctrl;
        int retval;
 
-       if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+       if (serial_paranoia_check(info, tty->name, __func__))
                return -ENODEV;
 
        card = info->card;
@@ -3727,8 +3760,8 @@ static void cy_break(struct tty_struct *tty, int break_state)
        spin_unlock_irqrestore(&card->card_lock, flags);
 }                              /* cy_break */
 
-static int
-get_mon_info(struct cyclades_port *info, struct cyclades_monitor __user * mon)
+static int get_mon_info(struct cyclades_port *info,
+                               struct cyclades_monitor __user *mon)
 {
 
        if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
@@ -3767,8 +3800,8 @@ static int set_threshold(struct cyclades_port *info, unsigned long value)
        return 0;
 }                              /* set_threshold */
 
-static int
-get_threshold(struct cyclades_port *info, unsigned long __user * value)
+static int get_threshold(struct cyclades_port *info,
+                                               unsigned long __user *value)
 {
        struct cyclades_card *card;
        void __iomem *base_addr;
@@ -3789,15 +3822,15 @@ get_threshold(struct cyclades_port *info, unsigned long __user * value)
        return 0;
 }                              /* get_threshold */
 
-static int
-set_default_threshold(struct cyclades_port *info, unsigned long value)
+static int set_default_threshold(struct cyclades_port *info,
+                                                       unsigned long value)
 {
        info->default_threshold = value & 0x0f;
        return 0;
 }                              /* set_default_threshold */
 
-static int
-get_default_threshold(struct cyclades_port *info, unsigned long __user * value)
+static int get_default_threshold(struct cyclades_port *info,
+                                               unsigned long __user *value)
 {
        return put_user(info->default_threshold, value);
 }                              /* get_default_threshold */
@@ -3824,7 +3857,8 @@ static int set_timeout(struct cyclades_port *info, unsigned long value)
        return 0;
 }                              /* set_timeout */
 
-static int get_timeout(struct cyclades_port *info, unsigned long __user * value)
+static int get_timeout(struct cyclades_port *info,
+                                               unsigned long __user *value)
 {
        struct cyclades_card *card;
        void __iomem *base_addr;
@@ -3851,8 +3885,8 @@ static int set_default_timeout(struct cyclades_port *info, unsigned long value)
        return 0;
 }                              /* set_default_timeout */
 
-static int
-get_default_timeout(struct cyclades_port *info, unsigned long __user * value)
+static int get_default_timeout(struct cyclades_port *info,
+                                       unsigned long __user *value)
 {
        return put_user(info->default_timeout, value);
 }                              /* get_default_timeout */
@@ -3880,6 +3914,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
        printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n",
                info->line, cmd, arg);
 #endif
+       lock_kernel();
 
        switch (cmd) {
        case CYGETMON:
@@ -3936,7 +3971,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
                break;
 #endif                         /* CONFIG_CYZ_INTR */
        case CYSETWAIT:
-               info->closing_wait = (unsigned short)arg *HZ / 100;
+               info->closing_wait = (unsigned short)arg * HZ / 100;
                ret_val = 0;
                break;
        case CYGETWAIT:
@@ -3988,47 +4023,47 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
                p_cuser = argp;
                ret_val = put_user(cnow.cts, &p_cuser->cts);
                if (ret_val)
-                       return ret_val;
+                       break;
                ret_val = put_user(cnow.dsr, &p_cuser->dsr);
                if (ret_val)
-                       return ret_val;
+                       break;
                ret_val = put_user(cnow.rng, &p_cuser->rng);
                if (ret_val)
-                       return ret_val;
+                       break;
                ret_val = put_user(cnow.dcd, &p_cuser->dcd);
                if (ret_val)
-                       return ret_val;
+                       break;
                ret_val = put_user(cnow.rx, &p_cuser->rx);
                if (ret_val)
-                       return ret_val;
+                       break;
                ret_val = put_user(cnow.tx, &p_cuser->tx);
                if (ret_val)
-                       return ret_val;
+                       break;
                ret_val = put_user(cnow.frame, &p_cuser->frame);
                if (ret_val)
-                       return ret_val;
+                       break;
                ret_val = put_user(cnow.overrun, &p_cuser->overrun);
                if (ret_val)
-                       return ret_val;
+                       break;
                ret_val = put_user(cnow.parity, &p_cuser->parity);
                if (ret_val)
-                       return ret_val;
+                       break;
                ret_val = put_user(cnow.brk, &p_cuser->brk);
                if (ret_val)
-                       return ret_val;
+                       break;
                ret_val = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
                if (ret_val)
-                       return ret_val;
+                       break;
                ret_val = 0;
                break;
        default:
                ret_val = -ENOIOCTLCMD;
        }
+       unlock_kernel();
 
 #ifdef CY_DEBUG_OTHER
        printk(KERN_DEBUG "cyc:cy_ioctl done\n");
 #endif
-
        return ret_val;
 }                              /* cy_ioctl */
 
@@ -4113,9 +4148,8 @@ static void cy_throttle(struct tty_struct *tty)
                        tty->ldisc.chars_in_buffer(tty), info->line);
 #endif
 
-       if (serial_paranoia_check(info, tty->name, "cy_throttle")) {
+       if (serial_paranoia_check(info, tty->name, "cy_throttle"))
                return;
-       }
 
        card = info->card;
 
@@ -4169,12 +4203,11 @@ static void cy_unthrottle(struct tty_struct *tty)
        char buf[64];
 
        printk(KERN_DEBUG "cyc:unthrottle %s: %ld...ttyC%d\n",
-               tty_name(tty, buf), tty->ldisc.chars_in_buffer(tty),info->line);
+               tty_name(tty, buf), tty_chars_in_buffer(tty), info->line);
 #endif
 
-       if (serial_paranoia_check(info, tty->name, "cy_unthrottle")) {
+       if (serial_paranoia_check(info, tty->name, "cy_unthrottle"))
                return;
-       }
 
        if (I_IXOFF(tty)) {
                if (info->x_char)
@@ -4269,47 +4302,14 @@ static void cy_start(struct tty_struct *tty)
                base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index);
 
                spin_lock_irqsave(&cinfo->card_lock, flags);
-               cy_writeb(base_addr + (CyCAR << index), (u_char) (channel & 0x0003));   /* index channel */
+               cy_writeb(base_addr + (CyCAR << index),
+                       (u_char) (channel & 0x0003));   /* index channel */
                cy_writeb(base_addr + (CySRER << index),
                          readb(base_addr + (CySRER << index)) | CyTxRdy);
                spin_unlock_irqrestore(&cinfo->card_lock, flags);
        }
 }                              /* cy_start */
 
-static void cy_flush_buffer(struct tty_struct *tty)
-{
-       struct cyclades_port *info = tty->driver_data;
-       struct cyclades_card *card;
-       int channel, retval;
-       unsigned long flags;
-
-#ifdef CY_DEBUG_IO
-       printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line);
-#endif
-
-       if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
-               return;
-
-       card = info->card;
-       channel = info->line - card->first_line;
-
-       spin_lock_irqsave(&card->card_lock, flags);
-       info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-       spin_unlock_irqrestore(&card->card_lock, flags);
-
-       if (IS_CYC_Z(*card)) {  /* If it is a Z card, flush the on-board
-                                          buffers as well */
-               spin_lock_irqsave(&card->card_lock, flags);
-               retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L);
-               if (retval != 0) {
-                       printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d "
-                               "was %x\n", info->line, retval);
-               }
-               spin_unlock_irqrestore(&card->card_lock, flags);
-       }
-       tty_wakeup(tty);
-}                              /* cy_flush_buffer */
-
 /*
  * cy_hangup() --- called by tty_hangup() when a hangup is signaled.
  */
@@ -4406,10 +4406,11 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
                        info->cor3 = 0x08;      /* _very_ small rcv threshold */
 
                        chip_number = (port - cinfo->first_line) / 4;
-                       if ((info->chip_rev = readb(cinfo->base_addr +
-                                     (cy_chip_offset[chip_number] <<
-                                      index) + (CyGFRCR << index))) >=
-                           CD1400_REV_J) {
+                       info->chip_rev = readb(cinfo->base_addr +
+                                     (cy_chip_offset[chip_number] << index) +
+                                     (CyGFRCR << index));
+
+                       if (info->chip_rev >= CD1400_REV_J) {
                                /* It is a CD1400 rev. J or later */
                                info->tbpr = baud_bpr_60[13];   /* Tx BPR */
                                info->tco = baud_co_60[13];     /* Tx CO */
@@ -4454,7 +4455,8 @@ static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr,
        /* Cy_ClrIntr is 0x1800 */
        udelay(500L);
 
-       for (chip_number = 0; chip_number < CyMAX_CHIPS_PER_CARD; chip_number++) {
+       for (chip_number = 0; chip_number < CyMAX_CHIPS_PER_CARD;
+                                                       chip_number++) {
                base_addr =
                    true_base_addr + (cy_chip_offset[chip_number] << index);
                mdelay(1);
@@ -4555,12 +4557,11 @@ static int __init cy_detect_isa(void)
        /* scan the address table probing for Cyclom-Y/ISA boards */
        for (i = 0; i < NR_ISA_ADDRS; i++) {
                unsigned int isa_address = cy_isa_addresses[i];
-               if (isa_address == 0x0000) {
+               if (isa_address == 0x0000)
                        return nboard;
-               }
 
                /* probe for CD1400... */
-               cy_isa_address = ioremap(isa_address, CyISA_Ywin);
+               cy_isa_address = ioremap_nocache(isa_address, CyISA_Ywin);
                if (cy_isa_address == NULL) {
                        printk(KERN_ERR "Cyclom-Y/ISA: can't remap base "
                                        "address\n");
@@ -4847,12 +4848,10 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
        if (mailbox != 0) {
                /* set window to last 512K of RAM */
                cy_writel(&ctl_addr->loc_addr_base, WIN_RAM + RAM_SIZE);
-               //sleep(1);
                for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++)
                        cy_writeb(tmp, 255);
                /* set window to beginning of RAM */
                cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
-               //sleep(1);
        }
 
        retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, base_addr, NULL);
@@ -5382,7 +5381,8 @@ static void __exit cy_cleanup_module(void)
        del_timer_sync(&cyz_timerlist);
 #endif /* CONFIG_CYZ_INTR */
 
-       if ((e1 = tty_unregister_driver(cy_serial_driver)))
+       e1 = tty_unregister_driver(cy_serial_driver);
+       if (e1)
                printk(KERN_ERR "failed to unregister Cyclades serial "
                                "driver(%d)\n", e1);
 
index ecee3547a13f2216d076c62708293b7ee168767d..213b3ca3468e5bdaf1c80db13a7d8c2c5e44a38a 100644 (file)
@@ -160,7 +160,7 @@ struct drm_device;
  * \param arg arguments
  */
 #define DRM_ERROR(fmt, arg...) \
-       printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* " fmt , __FUNCTION__ , ##arg)
+       printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* " fmt , __func__ , ##arg)
 
 /**
  * Memory error output.
@@ -170,7 +170,7 @@ struct drm_device;
  * \param arg arguments
  */
 #define DRM_MEM_ERROR(area, fmt, arg...) \
-       printk(KERN_ERR "[" DRM_NAME ":%s:%s] *ERROR* " fmt , __FUNCTION__, \
+       printk(KERN_ERR "[" DRM_NAME ":%s:%s] *ERROR* " fmt , __func__, \
               drm_mem_stats[area].name , ##arg)
 
 #define DRM_INFO(fmt, arg...)  printk(KERN_INFO "[" DRM_NAME "] " fmt , ##arg)
@@ -187,7 +187,7 @@ struct drm_device;
                if ( drm_debug )                        \
                        printk(KERN_DEBUG                               \
                               "[" DRM_NAME ":%s] " fmt ,       \
-                              __FUNCTION__ , ##arg);                   \
+                              __func__ , ##arg);                       \
        } while (0)
 #else
 #define DRM_DEBUG(fmt, arg...)          do { } while (0)
@@ -238,7 +238,7 @@ do {                                                                        \
        if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) ||           \
             dev->lock.file_priv != file_priv ) {                       \
                DRM_ERROR( "%s called without lock held, held  %d owner %p %p\n",\
-                          __FUNCTION__, _DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ),\
+                          __func__, _DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ),\
                           dev->lock.file_priv, file_priv );            \
                return -EINVAL;                                         \
        }                                                               \
index 7a1d9a782ddb3469a3e5105a6dc0841bd468b2a3..9a32169e88fb9595036998ed8ef3c9f5543c9ac8 100644 (file)
@@ -34,7 +34,7 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
        struct drm_minor *drm_minor = to_drm_minor(dev);
        struct drm_device *drm_dev = drm_minor->dev;
 
-       printk(KERN_ERR "%s\n", __FUNCTION__);
+       printk(KERN_ERR "%s\n", __func__);
 
        if (drm_dev->driver->suspend)
                return drm_dev->driver->suspend(drm_dev, state);
index 60c9376be486635e9ab902c64af5acb06d3ad339..a86ab30b4620b14dffe1cb11009f3d0ababf0a21 100644 (file)
@@ -692,7 +692,7 @@ static void i830EmitState(struct drm_device * dev)
        drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
        unsigned int dirty = sarea_priv->dirty;
 
-       DRM_DEBUG("%s %x\n", __FUNCTION__, dirty);
+       DRM_DEBUG("%s %x\n", __func__, dirty);
 
        if (dirty & I830_UPLOAD_BUFFERS) {
                i830EmitDestVerified(dev, sarea_priv->BufferState);
@@ -1043,7 +1043,7 @@ static void i830_dma_dispatch_flip(struct drm_device * dev)
        RING_LOCALS;
 
        DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
-                 __FUNCTION__,
+                 __func__,
                  dev_priv->current_page,
                  dev_priv->sarea_priv->pf_current_page);
 
@@ -1206,7 +1206,7 @@ static void i830_dma_quiescent(struct drm_device * dev)
        OUT_RING(0);
        ADVANCE_LP_RING();
 
-       i830_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
+       i830_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
 }
 
 static int i830_flush_queue(struct drm_device * dev)
@@ -1223,7 +1223,7 @@ static int i830_flush_queue(struct drm_device * dev)
        OUT_RING(0);
        ADVANCE_LP_RING();
 
-       i830_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
+       i830_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
 
        for (i = 0; i < dma->buf_count; i++) {
                struct drm_buf *buf = dma->buflist[i];
@@ -1344,7 +1344,7 @@ static void i830_do_init_pageflip(struct drm_device * dev)
 {
        drm_i830_private_t *dev_priv = dev->dev_private;
 
-       DRM_DEBUG("%s\n", __FUNCTION__);
+       DRM_DEBUG("%s\n", __func__);
        dev_priv->page_flipping = 1;
        dev_priv->current_page = 0;
        dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
@@ -1354,7 +1354,7 @@ static int i830_do_cleanup_pageflip(struct drm_device * dev)
 {
        drm_i830_private_t *dev_priv = dev->dev_private;
 
-       DRM_DEBUG("%s\n", __FUNCTION__);
+       DRM_DEBUG("%s\n", __func__);
        if (dev_priv->current_page != 0)
                i830_dma_dispatch_flip(dev);
 
@@ -1367,7 +1367,7 @@ static int i830_flip_bufs(struct drm_device *dev, void *data,
 {
        drm_i830_private_t *dev_priv = dev->dev_private;
 
-       DRM_DEBUG("%s\n", __FUNCTION__);
+       DRM_DEBUG("%s\n", __func__);
 
        LOCK_TEST_WITH_RETURN(dev, file_priv);
 
@@ -1437,7 +1437,7 @@ static int i830_getparam(struct drm_device *dev, void *data,
        int value;
 
        if (!dev_priv) {
-               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+               DRM_ERROR("%s called with no initialization\n", __func__);
                return -EINVAL;
        }
 
@@ -1464,7 +1464,7 @@ static int i830_setparam(struct drm_device *dev, void *data,
        drm_i830_setparam_t *param = data;
 
        if (!dev_priv) {
-               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+               DRM_ERROR("%s called with no initialization\n", __func__);
                return -EINVAL;
        }
 
index 4caba8c54455582271385d3bc69ebf61b93ed632..b5bf8cc0fdaa5845387962584ef92af28b78011a 100644 (file)
@@ -158,7 +158,7 @@ extern int i830_driver_device_is_agp(struct drm_device * dev);
        if (I830_VERBOSE)                               \
                printk("BEGIN_LP_RING(%d)\n", (n));     \
        if (dev_priv->ring.space < n*4)                 \
-               i830_wait_ring(dev, n*4, __FUNCTION__);         \
+               i830_wait_ring(dev, n*4, __func__);             \
        outcount = 0;                                   \
        outring = dev_priv->ring.tail;                  \
        ringmask = dev_priv->ring.tail_mask;            \
index a33db5f0967fbbb798706ec6c3125347371b6f10..91ec2bb497e97d6622be7f38c048360402f4caf9 100644 (file)
@@ -58,7 +58,7 @@ static int i830_emit_irq(struct drm_device * dev)
        drm_i830_private_t *dev_priv = dev->dev_private;
        RING_LOCALS;
 
-       DRM_DEBUG("%s\n", __FUNCTION__);
+       DRM_DEBUG("%s\n", __func__);
 
        atomic_inc(&dev_priv->irq_emitted);
 
@@ -77,7 +77,7 @@ static int i830_wait_irq(struct drm_device * dev, int irq_nr)
        unsigned long end = jiffies + HZ * 3;
        int ret = 0;
 
-       DRM_DEBUG("%s\n", __FUNCTION__);
+       DRM_DEBUG("%s\n", __func__);
 
        if (atomic_read(&dev_priv->irq_received) >= irq_nr)
                return 0;
@@ -124,7 +124,7 @@ int i830_irq_emit(struct drm_device *dev, void *data,
        LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (!dev_priv) {
-               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+               DRM_ERROR("%s called with no initialization\n", __func__);
                return -EINVAL;
        }
 
@@ -147,7 +147,7 @@ int i830_irq_wait(struct drm_device *dev, void *data,
        drm_i830_irq_wait_t *irqwait = data;
 
        if (!dev_priv) {
-               DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+               DRM_ERROR("%s called with no initialization\n", __func__);
                return -EINVAL;
        }
 
index ef7bf143a80c632a9c8044fa7e0d77f4fbc3a57f..f47e46e3529fae1ef0be1049205de3f245210a49 100644 (file)
@@ -194,7 +194,7 @@ static int i915_dma_resume(struct drm_device * dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
-       DRM_DEBUG("%s\n", __FUNCTION__);
+       DRM_DEBUG("%s\n", __func__);
 
        if (!dev_priv->sarea) {
                DRM_ERROR("can not find sarea!\n");
@@ -609,7 +609,7 @@ static int i915_quiescent(struct drm_device * dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
 
        i915_kernel_lost_context(dev);
-       return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
+       return i915_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
 }
 
 static int i915_flush_ioctl(struct drm_device *dev, void *data,
index c614d78b3dfdfca2a69ba4bc5ee8c85e376760f1..db7001f22561f6ea1a1f745b512e4bf51fd6e8c7 100644 (file)
@@ -272,7 +272,7 @@ extern void i915_mem_release(struct drm_device * dev,
        if (I915_VERBOSE)                               \
                DRM_DEBUG("BEGIN_LP_RING(%d)\n", (n));  \
        if (dev_priv->ring.space < (n)*4)               \
-               i915_wait_ring(dev, (n)*4, __FUNCTION__);               \
+               i915_wait_ring(dev, (n)*4, __func__);           \
        outcount = 0;                                   \
        outring = dev_priv->ring.tail;                  \
        ringmask = dev_priv->ring.tail_mask;            \
index 9072e4a1894e4d773a64b82cf72865f04b4db1fb..f6f6c92bf7710ad4c60892dc165eabaf50693219 100644 (file)
@@ -894,7 +894,7 @@ static u32 RADEON_READ_IGPGART(drm_radeon_private_t *dev_priv, int addr)
 #if RADEON_FIFO_DEBUG
 static void radeon_status(drm_radeon_private_t * dev_priv)
 {
-       printk("%s:\n", __FUNCTION__);
+       printk("%s:\n", __func__);
        printk("RBBM_STATUS = 0x%08x\n",
               (unsigned int)RADEON_READ(RADEON_RBBM_STATUS));
        printk("CP_RB_RTPR = 0x%08x\n",
index 59146e3365bac8bbda37b45d33297c0c9d071b7e..ea35ab2c9909490bb490bb51eae47d39c31661b3 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/spinlock.h>
 #include <linux/bcd.h>
 #include <linux/proc_fs.h>
+#include <linux/jiffies.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -451,7 +452,7 @@ static void ds1286_get_time(struct rtc_time *rtc_tm)
         */
 
        if (ds1286_is_updating() != 0)
-               while (jiffies - uip_watchdog < 2*HZ/100)
+               while (time_before(jiffies, uip_watchdog + 2*HZ/100))
                        barrier();
 
        /*
index ffd747c5dff00dc7e69a1835d078003dd7ffc3d7..60a4df7dac12ed9e073c29c991e97178d42c7e1b 100644 (file)
@@ -38,8 +38,8 @@
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
 #include <linux/spinlock.h>
 #include <linux/pci.h>
 #include "digiPCI.h"
@@ -73,7 +73,8 @@ static int invalid_lilo_config;
  */
 static DEFINE_SPINLOCK(epca_lock);
 
-/* MAXBOARDS is typically 12, but ISA and EISA cards are restricted to 7 below. */
+/* MAXBOARDS is typically 12, but ISA and EISA cards are restricted
+   to 7 below. */
 static struct board_info boards[MAXBOARDS];
 
 static struct tty_driver *pc_driver;
@@ -157,13 +158,12 @@ static void epca_error(int, char *);
 static void pc_close(struct tty_struct *, struct file *);
 static void shutdown(struct channel *);
 static void pc_hangup(struct tty_struct *);
-static void pc_put_char(struct tty_struct *, unsigned char);
 static int pc_write_room(struct tty_struct *);
 static int pc_chars_in_buffer(struct tty_struct *);
 static void pc_flush_buffer(struct tty_struct *);
 static void pc_flush_chars(struct tty_struct *);
 static int block_til_ready(struct tty_struct *, struct file *,
-                           struct channel *);
+                       struct channel *);
 static int pc_open(struct tty_struct *, struct file *);
 static void post_fep_init(unsigned int crd);
 static void epcapoll(unsigned long);
@@ -175,18 +175,18 @@ static unsigned termios2digi_c(struct channel *ch, unsigned);
 static void epcaparam(struct tty_struct *, struct channel *);
 static void receive_data(struct channel *);
 static int pc_ioctl(struct tty_struct *, struct file *,
-                    unsigned int, unsigned long);
+                       unsigned int, unsigned long);
 static int info_ioctl(struct tty_struct *, struct file *,
-                    unsigned int, unsigned long);
+                       unsigned int, unsigned long);
 static void pc_set_termios(struct tty_struct *, struct ktermios *);
 static void do_softint(struct work_struct *work);
 static void pc_stop(struct tty_struct *);
 static void pc_start(struct tty_struct *);
-static void pc_throttle(struct tty_struct * tty);
+static void pc_throttle(struct tty_struct *tty);
 static void pc_unthrottle(struct tty_struct *tty);
 static void digi_send_break(struct channel *ch, int msec);
 static void setup_empty_event(struct tty_struct *tty, struct channel *ch);
-void epca_setup(char *, int *);
+static void epca_setup(char *, int *);
 
 static int pc_write(struct tty_struct *, const unsigned char *, int);
 static int pc_init(void);
@@ -243,7 +243,7 @@ static void assertmemoff(struct channel *ch)
 /* PCXEM windowing is the same as that used in the PCXR and CX series cards. */
 static void pcxem_memwinon(struct board_info *b, unsigned int win)
 {
-        outb_p(FEPWIN|win, b->port + 1);
+       outb_p(FEPWIN | win, b->port + 1);
 }
 
 static void pcxem_memwinoff(struct board_info *b, unsigned int win)
@@ -253,7 +253,7 @@ static void pcxem_memwinoff(struct board_info *b, unsigned int win)
 
 static void pcxem_globalwinon(struct channel *ch)
 {
-       outb_p( FEPWIN, (int)ch->board->port + 1);
+       outb_p(FEPWIN, (int)ch->board->port + 1);
 }
 
 static void pcxem_rxwinon(struct channel *ch)
@@ -394,7 +394,7 @@ static struct channel *verifyChannel(struct tty_struct *tty)
         */
        if (tty) {
                struct channel *ch = (struct channel *)tty->driver_data;
-               if ((ch >= &digi_channels[0]) && (ch < &digi_channels[nbdevs])) {
+               if (ch >= &digi_channels[0] && ch < &digi_channels[nbdevs]) {
                        if (ch->magic == EPCA_MAGIC)
                                return ch;
                }
@@ -414,7 +414,7 @@ static void pc_sched_event(struct channel *ch, int event)
 
 static void epca_error(int line, char *msg)
 {
-       printk(KERN_ERR "epca_error (Digi): line = %d %s\n",line,msg);
+       printk(KERN_ERR "epca_error (Digi): line = %d %s\n", line, msg);
 }
 
 static void pc_close(struct tty_struct *tty, struct file *filp)
@@ -425,7 +425,8 @@ static void pc_close(struct tty_struct *tty, struct file *filp)
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) != NULL) {
+       ch = verifyChannel(tty);
+       if (ch != NULL) {
                spin_lock_irqsave(&epca_lock, flags);
                if (tty_hung_up_p(filp)) {
                        spin_unlock_irqrestore(&epca_lock, flags);
@@ -440,7 +441,6 @@ static void pc_close(struct tty_struct *tty, struct file *filp)
                        spin_unlock_irqrestore(&epca_lock, flags);
                        return;
                }
-
                /* Port open only once go ahead with shutdown & reset */
                BUG_ON(ch->count < 0);
 
@@ -455,12 +455,13 @@ static void pc_close(struct tty_struct *tty, struct file *filp)
                spin_unlock_irqrestore(&epca_lock, flags);
 
                if (ch->asyncflags & ASYNC_INITIALIZED)  {
-                       /* Setup an event to indicate when the transmit buffer empties */
+                       /* Setup an event to indicate when the
+                          transmit buffer empties */
                        setup_empty_event(tty, ch);
-                       tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
+                       /* 30 seconds timeout */
+                       tty_wait_until_sent(tty, 3000);
                }
-               if (tty->driver->flush_buffer)
-                       tty->driver->flush_buffer(tty);
+               pc_flush_buffer(tty);
 
                tty_ldisc_flush(tty);
                shutdown(ch);
@@ -477,7 +478,7 @@ static void pc_close(struct tty_struct *tty, struct file *filp)
                        wake_up_interruptible(&ch->open_wait);
                }
                ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED |
-                                     ASYNC_CLOSING);
+                                       ASYNC_CLOSING);
                wake_up_interruptible(&ch->close_wait);
        }
 }
@@ -524,16 +525,15 @@ static void shutdown(struct channel *ch)
 static void pc_hangup(struct tty_struct *tty)
 {
        struct channel *ch;
-
        /*
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) != NULL) {
+       ch = verifyChannel(tty);
+       if (ch != NULL) {
                unsigned long flags;
 
-               if (tty->driver->flush_buffer)
-                       tty->driver->flush_buffer(tty);
+               pc_flush_buffer(tty);
                tty_ldisc_flush(tty);
                shutdown(ch);
 
@@ -548,7 +548,7 @@ static void pc_hangup(struct tty_struct *tty)
 }
 
 static int pc_write(struct tty_struct *tty,
-                    const unsigned char *buf, int bytesAvailable)
+                       const unsigned char *buf, int bytesAvailable)
 {
        unsigned int head, tail;
        int dataLen;
@@ -572,7 +572,8 @@ static int pc_write(struct tty_struct *tty,
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) == NULL)
+       ch = verifyChannel(tty);
+       if (ch == NULL)
                return 0;
 
        /* Make a pointer to the channel data structure found on the board. */
@@ -645,26 +646,19 @@ static int pc_write(struct tty_struct *tty,
        return amountCopied;
 }
 
-static void pc_put_char(struct tty_struct *tty, unsigned char c)
-{
-       pc_write(tty, &c, 1);
-}
-
 static int pc_write_room(struct tty_struct *tty)
 {
-       int remain;
+       int remain = 0;
        struct channel *ch;
        unsigned long flags;
        unsigned int head, tail;
        struct board_chan __iomem *bc;
-
-       remain = 0;
-
        /*
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) != NULL)  {
+       ch = verifyChannel(tty);
+       if (ch != NULL) {
                spin_lock_irqsave(&epca_lock, flags);
                globalwinon(ch);
 
@@ -676,8 +670,8 @@ static int pc_write_room(struct tty_struct *tty)
                        tail = readw(&bc->tout);
                /* Wrap tail if necessary */
                tail &= (ch->txbufsize - 1);
-
-               if ((remain = tail - head - 1) < 0 )
+               remain = tail - head - 1;
+               if (remain < 0)
                        remain += ch->txbufsize;
 
                if (remain && (ch->statusflags & LOWWAIT) == 0) {
@@ -699,12 +693,12 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
        unsigned long flags;
        struct channel *ch;
        struct board_chan __iomem *bc;
-
        /*
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) == NULL)
+       ch = verifyChannel(tty);
+       if (ch == NULL)
                return 0;
 
        spin_lock_irqsave(&epca_lock, flags);
@@ -715,7 +709,8 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
        head = readw(&bc->tin);
        ctail = readw(&ch->mailbox->cout);
 
-       if (tail == head && readw(&ch->mailbox->cin) == ctail && readb(&bc->tbusy) == 0)
+       if (tail == head && readw(&ch->mailbox->cin) == ctail &&
+                                               readb(&bc->tbusy) == 0)
                chars = 0;
        else  { /* Begin if some space on the card has been used */
                head = readw(&bc->tin) & (ch->txbufsize - 1);
@@ -725,7 +720,8 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
                 * pc_write_room here we are finding the amount of bytes in the
                 * buffer filled. Not the amount of bytes empty.
                 */
-               if ((remain = tail - head - 1) < 0 )
+               remain = tail - head - 1;
+               if (remain < 0)
                        remain += ch->txbufsize;
                chars = (int)(ch->txbufsize - remain);
                /*
@@ -736,7 +732,7 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
                 * transmit buffer empties.
                 */
                if (!(ch->statusflags & EMPTYWAIT))
-                       setup_empty_event(tty,ch);
+                       setup_empty_event(tty, ch);
        } /* End if some space on the card has been used */
        memoff(ch);
        spin_unlock_irqrestore(&epca_lock, flags);
@@ -754,7 +750,8 @@ static void pc_flush_buffer(struct tty_struct *tty)
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) == NULL)
+       ch = verifyChannel(tty);
+       if (ch == NULL)
                return;
 
        spin_lock_irqsave(&epca_lock, flags);
@@ -775,23 +772,25 @@ static void pc_flush_chars(struct tty_struct *tty)
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) != NULL) {
+       ch = verifyChannel(tty);
+       if (ch != NULL) {
                unsigned long flags;
                spin_lock_irqsave(&epca_lock, flags);
                /*
                 * If not already set and the transmitter is busy setup an
                 * event to indicate when the transmit empties.
                 */
-               if ((ch->statusflags & TXBUSY) && !(ch->statusflags & EMPTYWAIT))
-                       setup_empty_event(tty,ch);
+               if ((ch->statusflags & TXBUSY) &&
+                               !(ch->statusflags & EMPTYWAIT))
+                       setup_empty_event(tty, ch);
                spin_unlock_irqrestore(&epca_lock, flags);
        }
 }
 
 static int block_til_ready(struct tty_struct *tty,
-                           struct file *filp, struct channel *ch)
+                               struct file *filp, struct channel *ch)
 {
-       DECLARE_WAITQUEUE(wait,current);
+       DECLARE_WAITQUEUE(wait, current);
        int retval, do_clocal = 0;
        unsigned long flags;
 
@@ -839,8 +838,7 @@ static int block_til_ready(struct tty_struct *tty,
        while (1) {
                set_current_state(TASK_INTERRUPTIBLE);
                if (tty_hung_up_p(filp) ||
-                   !(ch->asyncflags & ASYNC_INITIALIZED))
-               {
+                               !(ch->asyncflags & ASYNC_INITIALIZED)) {
                        if (ch->asyncflags & ASYNC_HUP_NOTIFY)
                                retval = -EAGAIN;
                        else
@@ -880,7 +878,7 @@ static int block_til_ready(struct tty_struct *tty,
        return 0;
 }
 
-static int pc_open(struct tty_struct *tty, struct file * filp)
+static int pc_open(struct tty_struct *tty, struct file *filp)
 {
        struct channel *ch;
        unsigned long flags;
@@ -923,7 +921,8 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
                return(-ENODEV);
        }
 
-       if ((bc = ch->brdchan) == 0) {
+       bc = ch->brdchan;
+       if (bc == NULL) {
                tty->driver_data = NULL;
                return -ENODEV;
        }
@@ -964,7 +963,7 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
         * The below routine generally sets up parity, baud, flow control
         * issues, etc.... It effect both control flags and input flags.
         */
-       epcaparam(tty,ch);
+       epcaparam(tty, ch);
        ch->asyncflags |= ASYNC_INITIALIZED;
        memoff(ch);
        spin_unlock_irqrestore(&epca_lock, flags);
@@ -1002,8 +1001,8 @@ static void __exit epca_module_exit(void)
 
        del_timer_sync(&epca_timer);
 
-       if (tty_unregister_driver(pc_driver) || tty_unregister_driver(pc_info))
-       {
+       if (tty_unregister_driver(pc_driver) ||
+                               tty_unregister_driver(pc_info)) {
                printk(KERN_WARNING "epca: cleanup_module failed to un-register tty driver\n");
                return;
        }
@@ -1034,7 +1033,6 @@ static const struct tty_operations pc_ops = {
        .flush_buffer = pc_flush_buffer,
        .chars_in_buffer = pc_chars_in_buffer,
        .flush_chars = pc_flush_chars,
-       .put_char = pc_put_char,
        .ioctl = pc_ioctl,
        .set_termios = pc_set_termios,
        .stop = pc_stop,
@@ -1044,7 +1042,7 @@ static const struct tty_operations pc_ops = {
        .hangup = pc_hangup,
 };
 
-static int info_open(struct tty_struct *tty, struct file * filp)
+static int info_open(struct tty_struct *tty, struct file *filp)
 {
        return 0;
 }
@@ -1099,7 +1097,7 @@ static int __init pc_init(void)
         * Set up interrupt, we will worry about memory allocation in
         * post_fep_init.
         */
-       printk(KERN_INFO "DIGI epca driver version %s loaded.\n",VERSION);
+       printk(KERN_INFO "DIGI epca driver version %s loaded.\n", VERSION);
 
        /*
         * NOTE : This code assumes that the number of ports found in the
@@ -1252,7 +1250,7 @@ static int __init pc_init(void)
                                if ((board_id & 0x30) == 0x30)
                                        bd->memory_seg = 0x8000;
                        } else
-                               printk(KERN_ERR "epca: Board at 0x%x doesn't appear to be an XI\n",(int)bd->port);
+                               printk(KERN_ERR "epca: Board at 0x%x doesn't appear to be an XI\n", (int)bd->port);
                        break;
                }
        }
@@ -1326,12 +1324,12 @@ static void post_fep_init(unsigned int crd)
                 */
                /* PCI cards are already remapped at this point ISA are not */
                bd->numports = readw(bd->re_map_membase + XEMPORTS);
-               epcaassert(bd->numports <= 64,"PCI returned a invalid number of ports");
+               epcaassert(bd->numports <= 64, "PCI returned a invalid number of ports");
                nbdevs += (bd->numports);
        } else {
                /* Fix up the mappings for ISA/EISA etc */
                /* FIXME: 64K - can we be smarter ? */
-               bd->re_map_membase = ioremap(bd->membase, 0x10000);
+               bd->re_map_membase = ioremap_nocache(bd->membase, 0x10000);
        }
 
        if (crd != 0)
@@ -1362,7 +1360,8 @@ static void post_fep_init(unsigned int crd)
         * XEPORTS (address 0xc22) points at the number of channels the card
         * supports. (For 64XE, XI, XEM, and XR use 0xc02)
         */
-       if ((bd->type == PCXEVE || bd->type == PCXE) && (readw(memaddr + XEPORTS) < 3))
+       if ((bd->type == PCXEVE || bd->type == PCXE) &&
+                                       (readw(memaddr + XEPORTS) < 3))
                shrinkmem = 1;
        if (bd->type < PCIXEM)
                if (!request_region((int)bd->port, 4, board_desc[bd->type]))
@@ -1461,10 +1460,12 @@ static void post_fep_init(unsigned int crd)
 
                case PCXEVE:
                case PCXE:
-                       ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4) & 0x1fff);
+                       ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4)
+                                                               & 0x1fff);
                        ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9);
-                       ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4) & 0x1fff);
-                       ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >>9 );
+                       ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4)
+                                                               & 0x1fff);
+                       ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >> 9);
                        break;
 
                case PCXI:
@@ -1518,8 +1519,9 @@ static void post_fep_init(unsigned int crd)
        }
 
        printk(KERN_INFO
-               "Digi PC/Xx Driver V%s:  %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n",
-               VERSION, board_desc[bd->type], (long)bd->port, (long)bd->membase, bd->numports);
+       "Digi PC/Xx Driver V%s:  %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n",
+                               VERSION, board_desc[bd->type], (long)bd->port,
+                                       (long)bd->membase, bd->numports);
        memwinoff(bd, 0);
 }
 
@@ -1527,7 +1529,7 @@ static void epcapoll(unsigned long ignored)
 {
        unsigned long flags;
        int crd;
-       volatile unsigned int head, tail;
+       unsigned int head, tail;
        struct channel *ch;
        struct board_info *bd;
 
@@ -1593,7 +1595,9 @@ static void doevent(int crd)
        chan0 = card_ptr[crd];
        epcaassert(chan0 <= &digi_channels[nbdevs - 1], "ch out of range");
        assertgwinon(chan0);
-       while ((tail = readw(&chan0->mailbox->eout)) != (head = readw(&chan0->mailbox->ein))) { /* Begin while something in event queue */
+       while ((tail = readw(&chan0->mailbox->eout)) !=
+                       (head = readw(&chan0->mailbox->ein))) {
+               /* Begin while something in event queue */
                assertgwinon(chan0);
                eventbuf = bd->re_map_membase + tail + ISTART;
                /* Get the channel the event occurred on */
@@ -1617,7 +1621,8 @@ static void doevent(int crd)
                        goto next;
                }
 
-               if ((bc = ch->brdchan) == NULL)
+               bc = ch->brdchan;
+               if (bc == NULL)
                        goto next;
 
                if (event & DATA_IND)  { /* Begin DATA_IND */
@@ -1629,10 +1634,11 @@ static void doevent(int crd)
                        /* A modem signal change has been indicated */
                        ch->imodem = mstat;
                        if (ch->asyncflags & ASYNC_CHECK_CD) {
-                               if (mstat & ch->dcd)  /* We are now receiving dcd */
+                               /* We are now receiving dcd */
+                               if (mstat & ch->dcd)
                                        wake_up_interruptible(&ch->open_wait);
-                               else
-                                       pc_sched_event(ch, EPCA_EVENT_HANGUP); /* No dcd; hangup */
+                               else    /* No dcd; hangup */
+                                       pc_sched_event(ch, EPCA_EVENT_HANGUP);
                        }
                }
                tty = ch->tty;
@@ -1647,7 +1653,8 @@ static void doevent(int crd)
                                        tty_wakeup(tty);
                                }
                        } else if (event & EMPTYTX_IND) {
-                               /* This event is generated by setup_empty_event */
+                               /* This event is generated by
+                                  setup_empty_event */
                                ch->statusflags &= ~TXBUSY;
                                if (ch->statusflags & EMPTYWAIT) {
                                        ch->statusflags &= ~EMPTYWAIT;
@@ -1655,7 +1662,7 @@ static void doevent(int crd)
                                }
                        }
                }
-       next:
+next:
                globalwinon(ch);
                BUG_ON(!bc);
                writew(1, &bc->idata);
@@ -1665,7 +1672,7 @@ static void doevent(int crd)
 }
 
 static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
-                   int byte2, int ncmds, int bytecmd)
+                                       int byte2, int ncmds, int bytecmd)
 {
        unchar __iomem *memaddr;
        unsigned int head, cmdTail, cmdStart, cmdMax;
@@ -1690,8 +1697,10 @@ static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
        memaddr = ch->board->re_map_membase;
 
        if (head >= (cmdMax - cmdStart) || (head & 03))  {
-               printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n", __LINE__,  cmd, head);
-               printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n", __LINE__,  cmdMax, cmdStart);
+               printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n",
+                                               __LINE__,  cmd, head);
+               printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n",
+                                               __LINE__,  cmdMax, cmdStart);
                return;
        }
        if (bytecmd)  {
@@ -1770,7 +1779,7 @@ static unsigned termios2digi_h(struct channel *ch, unsigned cflag)
 static unsigned termios2digi_i(struct channel *ch, unsigned iflag)
 {
        unsigned res = iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK |
-                               INPCK | ISTRIP|IXON|IXANY|IXOFF);
+                                       INPCK | ISTRIP | IXON | IXANY | IXOFF);
        if (ch->digiext.digi_flags & DIGI_AIXON)
                res |= IAIXON;
        return res;
@@ -1838,7 +1847,7 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
        unsigned mval, hflow, cflag, iflag;
 
        bc = ch->brdchan;
-       epcaassert(bc !=0, "bc out of range");
+       epcaassert(bc != NULL, "bc out of range");
 
        assertgwinon(ch);
        ts = tty->termios;
@@ -1884,8 +1893,10 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
                 * Command sets channels iflag structure on the board. Such
                 * things as input soft flow control, handling of parity
                 * errors, and break handling are all set here.
+                *
+                * break handling, parity handling, input stripping,
+                * flow control chars
                 */
-               /* break handling, parity handling, input stripping, flow control chars */
                fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0);
        }
        /*
@@ -1981,7 +1992,7 @@ static void receive_data(struct channel *ch)
                return;
 
        /* If CREAD bit is off or device not open, set TX tail to head */
-       if (!tty || !ts || !(ts->c_cflag & CREAD))  {
+       if (!tty || !ts || !(ts->c_cflag & CREAD)) {
                writew(head, &bc->rout);
                return;
        }
@@ -1991,18 +2002,21 @@ static void receive_data(struct channel *ch)
 
        if (readb(&bc->orun)) {
                writeb(0, &bc->orun);
-               printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n",tty->name);
+               printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n",
+                                                               tty->name);
                tty_insert_flip_char(tty, 0, TTY_OVERRUN);
        }
        rxwinon(ch);
-       while (bytesAvailable > 0)  { /* Begin while there is data on the card */
+       while (bytesAvailable > 0) {
+               /* Begin while there is data on the card */
                wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail;
                /*
                 * Even if head has wrapped around only report the amount of
                 * data to be equal to the size - tail. Remember memcpy can't
                 * automaticly wrap around the receive buffer.
                 */
-               dataToRead = (wrapgap < bytesAvailable) ? wrapgap : bytesAvailable;
+               dataToRead = (wrapgap < bytesAvailable) ? wrapgap
+                                                       : bytesAvailable;
                /* Make sure we don't overflow the buffer */
                dataToRead = tty_prepare_flip_string(tty, &rptr, dataToRead);
                if (dataToRead == 0)
@@ -2153,14 +2167,14 @@ static int pc_tiocmset(struct tty_struct *tty, struct file *file,
         * The below routine generally sets up parity, baud, flow control
         * issues, etc.... It effect both control flags and input flags.
         */
-       epcaparam(tty,ch);
+       epcaparam(tty, ch);
        memoff(ch);
        spin_unlock_irqrestore(&epca_lock, flags);
        return 0;
 }
 
-static int pc_ioctl(struct tty_struct *tty, struct file * file,
-                   unsigned int cmd, unsigned long arg)
+static int pc_ioctl(struct tty_struct *tty, struct file *file,
+                                       unsigned int cmd, unsigned long arg)
 {
        digiflow_t dflow;
        int retval;
@@ -2175,7 +2189,6 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
                bc = ch->brdchan;
        else
                return -EINVAL;
-
        /*
         * For POSIX compliance we need to add more ioctls. See tty_ioctl.c in
         * /usr/src/linux/drivers/char for a good example. In particular think
@@ -2186,9 +2199,10 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
                retval = tty_check_change(tty);
                if (retval)
                        return retval;
-               /* Setup an event to indicate when the transmit buffer empties */
+               /* Setup an event to indicate when the transmit
+                  buffer empties */
                spin_lock_irqsave(&epca_lock, flags);
-               setup_empty_event(tty,ch);
+               setup_empty_event(tty, ch);
                spin_unlock_irqrestore(&epca_lock, flags);
                tty_wait_until_sent(tty, 0);
                if (!arg)
@@ -2198,29 +2212,14 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
                retval = tty_check_change(tty);
                if (retval)
                        return retval;
-
-               /* Setup an event to indicate when the transmit buffer empties */
+               /* Setup an event to indicate when the transmit buffer
+                  empties */
                spin_lock_irqsave(&epca_lock, flags);
-               setup_empty_event(tty,ch);
+               setup_empty_event(tty, ch);
                spin_unlock_irqrestore(&epca_lock, flags);
                tty_wait_until_sent(tty, 0);
                digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4);
                return 0;
-       case TIOCGSOFTCAR:
-               if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)arg))
-                       return -EFAULT;
-               return 0;
-       case TIOCSSOFTCAR:
-               {
-                       unsigned int value;
-
-                       if (get_user(value, (unsigned __user *)argp))
-                               return -EFAULT;
-                       tty->termios->c_cflag =
-                               ((tty->termios->c_cflag & ~CLOCAL) |
-                                (value ? CLOCAL : 0));
-                       return 0;
-               }
        case TIOCMODG:
                mflag = pc_tiocmget(tty, file);
                if (put_user(mflag, (unsigned long __user *)argp))
@@ -2253,10 +2252,12 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
                break;
        case DIGI_SETAW:
        case DIGI_SETAF:
+               lock_kernel();
                if (cmd == DIGI_SETAW) {
-                       /* Setup an event to indicate when the transmit buffer empties */
+                       /* Setup an event to indicate when the transmit
+                          buffer empties */
                        spin_lock_irqsave(&epca_lock, flags);
-                       setup_empty_event(tty,ch);
+                       setup_empty_event(tty, ch);
                        spin_unlock_irqrestore(&epca_lock, flags);
                        tty_wait_until_sent(tty, 0);
                } else {
@@ -2264,6 +2265,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
                        if (tty->ldisc.flush_buffer)
                                tty->ldisc.flush_buffer(tty);
                }
+               unlock_kernel();
                /* Fall Thru */
        case DIGI_SETA:
                if (copy_from_user(&ch->digiext, argp, sizeof(digi_t)))
@@ -2285,7 +2287,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
                 * control issues, etc.... It effect both control flags and
                 * input flags.
                 */
-               epcaparam(tty,ch);
+               epcaparam(tty, ch);
                memoff(ch);
                spin_unlock_irqrestore(&epca_lock, flags);
                break;
@@ -2321,18 +2323,21 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
                if (copy_from_user(&dflow, argp, sizeof(dflow)))
                        return -EFAULT;
 
-               if (dflow.startc != startc || dflow.stopc != stopc) { /* Begin  if setflow toggled */
+               if (dflow.startc != startc || dflow.stopc != stopc) {
+                       /* Begin  if setflow toggled */
                        spin_lock_irqsave(&epca_lock, flags);
                        globalwinon(ch);
 
                        if (cmd == DIGI_SETFLOW) {
                                ch->fepstartc = ch->startc = dflow.startc;
                                ch->fepstopc = ch->stopc = dflow.stopc;
-                               fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1);
+                               fepcmd(ch, SONOFFC, ch->fepstartc,
+                                               ch->fepstopc, 0, 1);
                        } else {
                                ch->fepstartca = ch->startca = dflow.startc;
                                ch->fepstopca  = ch->stopca = dflow.stopc;
-                               fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
+                               fepcmd(ch, SAUXONOFFC, ch->fepstartca,
+                                               ch->fepstopca, 0, 1);
                        }
 
                        if (ch->statusflags & TXSTOPPED)
@@ -2356,7 +2361,9 @@ static void pc_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) != NULL)  { /* Begin if channel valid */
+       ch = verifyChannel(tty);
+
+       if (ch != NULL)  { /* Begin if channel valid */
                spin_lock_irqsave(&epca_lock, flags);
                globalwinon(ch);
                epcaparam(tty, ch);
@@ -2383,7 +2390,7 @@ static void do_softint(struct work_struct *work)
 
                if (tty && tty->driver_data) {
                        if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) {
-                               tty_hangup(tty);        /* FIXME: module removal race here - AKPM */
+                               tty_hangup(tty);
                                wake_up_interruptible(&ch->open_wait);
                                ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
                        }
@@ -2403,9 +2410,11 @@ static void pc_stop(struct tty_struct *tty)
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) != NULL) {
+       ch = verifyChannel(tty);
+       if (ch != NULL) {
                spin_lock_irqsave(&epca_lock, flags);
-               if ((ch->statusflags & TXSTOPPED) == 0) { /* Begin if transmit stop requested */
+               if ((ch->statusflags & TXSTOPPED) == 0) {
+                       /* Begin if transmit stop requested */
                        globalwinon(ch);
                        /* STOP transmitting now !! */
                        fepcmd(ch, PAUSETX, 0, 0, 0, 0);
@@ -2423,11 +2432,14 @@ static void pc_start(struct tty_struct *tty)
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) != NULL) {
+       ch = verifyChannel(tty);
+       if (ch != NULL) {
                unsigned long flags;
                spin_lock_irqsave(&epca_lock, flags);
-               /* Just in case output was resumed because of a change in Digi-flow */
-               if (ch->statusflags & TXSTOPPED)  { /* Begin transmit resume requested */
+               /* Just in case output was resumed because of a change
+                  in Digi-flow */
+               if (ch->statusflags & TXSTOPPED)  {
+                       /* Begin transmit resume requested */
                        struct board_chan __iomem *bc;
                        globalwinon(ch);
                        bc = ch->brdchan;
@@ -2457,7 +2469,8 @@ static void pc_throttle(struct tty_struct *tty)
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) != NULL) {
+       ch = verifyChannel(tty);
+       if (ch != NULL) {
                spin_lock_irqsave(&epca_lock, flags);
                if ((ch->statusflags & RXSTOPPED) == 0) {
                        globalwinon(ch);
@@ -2477,8 +2490,10 @@ static void pc_unthrottle(struct tty_struct *tty)
         * verifyChannel returns the channel from the tty struct if it is
         * valid. This serves as a sanity check.
         */
-       if ((ch = verifyChannel(tty)) != NULL) {
-               /* Just in case output was resumed because of a change in Digi-flow */
+       ch = verifyChannel(tty);
+       if (ch != NULL) {
+               /* Just in case output was resumed because of a change
+                  in Digi-flow */
                spin_lock_irqsave(&epca_lock, flags);
                if (ch->statusflags & RXSTOPPED) {
                        globalwinon(ch);
@@ -2490,7 +2505,7 @@ static void pc_unthrottle(struct tty_struct *tty)
        }
 }
 
-void digi_send_break(struct channel *ch, int msec)
+static void digi_send_break(struct channel *ch, int msec)
 {
        unsigned long flags;
 
@@ -2523,7 +2538,7 @@ static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
        memoff(ch);
 }
 
-void epca_setup(char *str, int *ints)
+static void epca_setup(char *str, int *ints)
 {
        struct board_info board;
        int               index, loop, last;
@@ -2552,14 +2567,16 @@ void epca_setup(char *str, int *ints)
                         * instructing the driver to ignore epcaconfig.) For
                         * this reason we check for 2.
                         */
-                       if (board.status == 2) { /* Begin ignore epcaconfig as well as lilo cmd line */
+                       if (board.status == 2) {
+                       /* Begin ignore epcaconfig as well as lilo cmd line */
                                nbdevs = 0;
                                num_cards = 0;
                                return;
                        } /* End ignore epcaconfig as well as lilo cmd line */
 
                        if (board.status > 2) {
-                               printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n", board.status);
+                               printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n",
+                                               board.status);
                                invalid_lilo_config = 1;
                                setup_error_code |= INVALID_BOARD_STATUS;
                                return;
@@ -2613,7 +2630,8 @@ void epca_setup(char *str, int *ints)
                case 6:
                        board.membase = ints[index];
                        if (ints[index] <= 0) {
-                               printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n",(unsigned int)board.membase);
+                               printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n",
+                                       (unsigned int)board.membase);
                                invalid_lilo_config = 1;
                                setup_error_code |= INVALID_MEM_BASE;
                                return;
@@ -2744,7 +2762,7 @@ void epca_setup(char *str, int *ints)
                                t2++;
 
                        if (*t2) {
-                               printk(KERN_ERR "epca_setup: Invalid memory base %s\n",str);
+                               printk(KERN_ERR "epca_setup: Invalid memory base %s\n", str);
                                invalid_lilo_config = 1;
                                setup_error_code |= INVALID_MEM_BASE;
                                return;
@@ -2766,7 +2784,7 @@ void epca_setup(char *str, int *ints)
 
        /* I should REALLY validate the stuff here */
        /* Copies our local copy of board into boards */
-       memcpy((void *)&boards[num_cards],(void *)&board, sizeof(board));
+       memcpy((void *)&boards[num_cards], (void *)&board, sizeof(board));
        /* Does this get called once per lilo arg are what ? */
        printk(KERN_INFO "PC/Xx: Added board %i, %s %i ports at 0x%4.4X base 0x%6.6X\n",
                num_cards, board_desc[board.type],
@@ -2807,9 +2825,9 @@ static int __devinit epca_init_one(struct pci_dev *pdev,
        if (board_idx >= MAXBOARDS)
                goto err_out;
 
-       addr = pci_resource_start (pdev, epca_info_tbl[info_idx].bar_idx);
+       addr = pci_resource_start(pdev, epca_info_tbl[info_idx].bar_idx);
        if (!addr) {
-               printk (KERN_ERR PFX "PCI region #%d not available (size 0)\n",
+               printk(KERN_ERR PFX "PCI region #%d not available (size 0)\n",
                        epca_info_tbl[info_idx].bar_idx);
                goto err_out;
        }
@@ -2820,28 +2838,29 @@ static int __devinit epca_init_one(struct pci_dev *pdev,
        boards[board_idx].port = addr + PCI_IO_OFFSET;
        boards[board_idx].membase = addr;
 
-       if (!request_mem_region (addr + PCI_IO_OFFSET, 0x200000, "epca")) {
-               printk (KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
+       if (!request_mem_region(addr + PCI_IO_OFFSET, 0x200000, "epca")) {
+               printk(KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
                        0x200000, addr + PCI_IO_OFFSET);
                goto err_out;
        }
 
-       boards[board_idx].re_map_port = ioremap(addr + PCI_IO_OFFSET, 0x200000);
+       boards[board_idx].re_map_port = ioremap_nocache(addr + PCI_IO_OFFSET,
+                                                               0x200000);
        if (!boards[board_idx].re_map_port) {
-               printk (KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n",
+               printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n",
                        0x200000, addr + PCI_IO_OFFSET);
                goto err_out_free_pciio;
        }
 
-       if (!request_mem_region (addr, 0x200000, "epca")) {
-               printk (KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
+       if (!request_mem_region(addr, 0x200000, "epca")) {
+               printk(KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
                        0x200000, addr);
                goto err_out_free_iounmap;
        }
 
-       boards[board_idx].re_map_membase = ioremap(addr, 0x200000);
+       boards[board_idx].re_map_membase = ioremap_nocache(addr, 0x200000);
        if (!boards[board_idx].re_map_membase) {
-               printk (KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n",
+               printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n",
                        0x200000, addr + PCI_IO_OFFSET);
                goto err_out_free_memregion;
        }
@@ -2858,11 +2877,11 @@ static int __devinit epca_init_one(struct pci_dev *pdev,
        return 0;
 
 err_out_free_memregion:
-       release_mem_region (addr, 0x200000);
+       release_mem_region(addr, 0x200000);
 err_out_free_iounmap:
-       iounmap (boards[board_idx].re_map_port);
+       iounmap(boards[board_idx].re_map_port);
 err_out_free_pciio:
-       release_mem_region (addr + PCI_IO_OFFSET, 0x200000);
+       release_mem_region(addr + PCI_IO_OFFSET, 0x200000);
 err_out:
        return -ENODEV;
 }
@@ -2878,9 +2897,9 @@ static struct pci_device_id epca_pci_tbl[] = {
 
 MODULE_DEVICE_TABLE(pci, epca_pci_tbl);
 
-int __init init_PCI (void)
+static int __init init_PCI(void)
 {
-       memset (&epca_driver, 0, sizeof (epca_driver));
+       memset(&epca_driver, 0, sizeof(epca_driver));
        epca_driver.name = "epca";
        epca_driver.id_table = epca_pci_tbl;
        epca_driver.probe = epca_init_one;
index f3fe620673440e267172e957f174028933beacbc..84840ba13ff05e584f78e3ca252eb0d74db10dd1 100644 (file)
@@ -8,7 +8,7 @@
  *  Extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92.  Now
  *  much more extensible to support other serial cards based on the
  *  16450/16550A UART's.  Added support for the AST FourPort and the
- *  Accent Async board.  
+ *  Accent Async board.
  *
  *  set_serial_info fixed to set the flags, custom divisor, and uart
  *     type fields.  Fix suggested by Michael K. Johnson 12/12/92.
 #include <linux/bitops.h>
 
 #include <asm/system.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 #include <asm/dma.h>
 #include <linux/slab.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <linux/hayesesp.h>
 
@@ -127,8 +127,10 @@ static struct tty_driver *esp_driver;
 #undef SERIAL_DEBUG_FLOW
 
 #if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
-#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
- tty->name, (info->flags), serial_driver.refcount,info->count,tty->count,s)
+#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
+                               tty->name, info->flags, \
+                               serial_driver.refcount, \
+                               info->count, tty->count, s)
 #else
 #define DBG_CNT(s)
 #endif
@@ -189,7 +191,7 @@ static inline void serial_out(struct esp_struct *info, int offset,
  */
 static void rs_stop(struct tty_struct *tty)
 {
-       struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+       struct esp_struct *info = tty->driver_data;
        unsigned long flags;
 
        if (serial_paranoia_check(info, tty->name, "rs_stop"))
@@ -206,12 +208,12 @@ static void rs_stop(struct tty_struct *tty)
 
 static void rs_start(struct tty_struct *tty)
 {
-       struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+       struct esp_struct *info = tty->driver_data;
        unsigned long flags;
-       
+
        if (serial_paranoia_check(info, tty->name, "rs_start"))
                return;
-       
+
        spin_lock_irqsave(&info->lock, flags);
        if (info->xmit_cnt && info->xmit_buf && !(info->IER & UART_IER_THRI)) {
                info->IER |= UART_IER_THRI;
@@ -233,7 +235,7 @@ static void rs_start(struct tty_struct *tty)
  * rs_interrupt() should try to keep the interrupt handler as fast as
  * possible.  After you are done making modifications, it is not a bad
  * idea to do:
- * 
+ *
  * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
  *
  * and look at the resulting assemble code in serial.s.
@@ -290,7 +292,7 @@ static inline void receive_chars_pio(struct esp_struct *info, int num_bytes)
        }
 
        status_mask = (info->read_status_mask >> 2) & 0x07;
-               
+
        for (i = 0; i < num_bytes - 1; i += 2) {
                *((unsigned short *)(pio_buf->data + i)) =
                        inw(info->port + UART_ESI_RX);
@@ -325,8 +327,7 @@ static inline void receive_chars_pio(struct esp_struct *info, int num_bytes)
                                flag = TTY_BREAK;
                                if (info->flags & ASYNC_SAK)
                                        do_SAK(tty);
-                       }
-                       else if (err_buf->data[i] & 0x02)
+                       } else if (err_buf->data[i] & 0x02)
                                flag = TTY_FRAME;
                        else if (err_buf->data[i] & 0x01)
                                flag = TTY_PARITY;
@@ -341,23 +342,29 @@ static inline void receive_chars_pio(struct esp_struct *info, int num_bytes)
        release_pio_buffer(err_buf);
 }
 
-static inline void receive_chars_dma(struct esp_struct *info, int num_bytes)
+static void program_isa_dma(int dma, int dir, unsigned long addr, int len)
 {
        unsigned long flags;
+
+       flags = claim_dma_lock();
+       disable_dma(dma);
+       clear_dma_ff(dma);
+       set_dma_mode(dma, dir);
+       set_dma_addr(dma, addr);
+       set_dma_count(dma, len);
+       enable_dma(dma);
+       release_dma_lock(flags);
+}
+
+static void receive_chars_dma(struct esp_struct *info, int num_bytes)
+{
        info->stat_flags &= ~ESP_STAT_RX_TIMEOUT;
        dma_bytes = num_bytes;
        info->stat_flags |= ESP_STAT_DMA_RX;
-       
-       flags=claim_dma_lock();
-        disable_dma(dma);
-        clear_dma_ff(dma);
-        set_dma_mode(dma, DMA_MODE_READ);
-        set_dma_addr(dma, isa_virt_to_bus(dma_buffer));
-        set_dma_count(dma, dma_bytes);
-        enable_dma(dma);
-        release_dma_lock(flags);
-        
-        serial_out(info, UART_ESI_CMD1, ESI_START_DMA_RX);
+
+       program_isa_dma(dma, DMA_MODE_READ, isa_virt_to_bus(dma_buffer),
+                                                               dma_bytes);
+       serial_out(info, UART_ESI_CMD1, ESI_START_DMA_RX);
 }
 
 static inline void receive_chars_dma_done(struct esp_struct *info,
@@ -366,22 +373,22 @@ static inline void receive_chars_dma_done(struct esp_struct *info,
        struct tty_struct *tty = info->tty;
        int num_bytes;
        unsigned long flags;
-       
-       flags=claim_dma_lock();
+
+       flags = claim_dma_lock();
        disable_dma(dma);
        clear_dma_ff(dma);
 
        info->stat_flags &= ~ESP_STAT_DMA_RX;
        num_bytes = dma_bytes - get_dma_residue(dma);
        release_dma_lock(flags);
-       
+
        info->icount.rx += num_bytes;
 
        if (num_bytes > 0) {
                tty_insert_flip_string(tty, dma_buffer, num_bytes - 1);
 
                status &= (0x1c & info->read_status_mask);
-               
+
                /* Is the status significant or do we throw the last byte ? */
                if (!(status & info->ignore_status_mask)) {
                        int statflag = 0;
@@ -393,13 +400,13 @@ static inline void receive_chars_dma_done(struct esp_struct *info,
                                        do_SAK(tty);
                        } else if (status & 0x08) {
                                statflag = TTY_FRAME;
-                               (info->icount.frame)++;
-                       }
-                       else if (status & 0x04) {
+                               info->icount.frame++;
+                       } else if (status & 0x04) {
                                statflag = TTY_PARITY;
-                               (info->icount.parity)++;
+                               info->icount.parity++;
                        }
-                       tty_insert_flip_char(tty, dma_buffer[num_bytes - 1], statflag);
+                       tty_insert_flip_char(tty, dma_buffer[num_bytes - 1],
+                                                               statflag);
                }
                tty_schedule_flip(tty);
        }
@@ -484,8 +491,6 @@ static inline void transmit_chars_pio(struct esp_struct *info,
 /* Caller must hold info->lock */
 static inline void transmit_chars_dma(struct esp_struct *info, int num_bytes)
 {
-       unsigned long flags;
-       
        dma_bytes = num_bytes;
 
        if (info->xmit_tail + dma_bytes <= ESP_XMIT_SIZE) {
@@ -517,26 +522,18 @@ static inline void transmit_chars_dma(struct esp_struct *info, int num_bytes)
        }
 
        info->stat_flags |= ESP_STAT_DMA_TX;
-       
-       flags=claim_dma_lock();
-        disable_dma(dma);
-        clear_dma_ff(dma);
-        set_dma_mode(dma, DMA_MODE_WRITE);
-        set_dma_addr(dma, isa_virt_to_bus(dma_buffer));
-        set_dma_count(dma, dma_bytes);
-        enable_dma(dma);
-        release_dma_lock(flags);
-        
-        serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX);
+
+       program_isa_dma(dma, DMA_MODE_WRITE, isa_virt_to_bus(dma_buffer),
+                                                               dma_bytes);
+       serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX);
 }
 
 static inline void transmit_chars_dma_done(struct esp_struct *info)
 {
        int num_bytes;
        unsigned long flags;
-       
 
-       flags=claim_dma_lock();
+       flags = claim_dma_lock();
        disable_dma(dma);
        clear_dma_ff(dma);
 
@@ -547,27 +544,21 @@ static inline void transmit_chars_dma_done(struct esp_struct *info)
        if (dma_bytes != num_bytes) {
                dma_bytes -= num_bytes;
                memmove(dma_buffer, dma_buffer + num_bytes, dma_bytes);
-               
-               flags=claim_dma_lock();
-               disable_dma(dma);
-               clear_dma_ff(dma);
-               set_dma_mode(dma, DMA_MODE_WRITE);
-               set_dma_addr(dma, isa_virt_to_bus(dma_buffer));
-               set_dma_count(dma, dma_bytes);
-               enable_dma(dma);
-               release_dma_lock(flags);
-               
-               serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX);
+
+               program_isa_dma(dma, DMA_MODE_WRITE,
+                               isa_virt_to_bus(dma_buffer), dma_bytes);
+
+               serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX);
        } else {
                dma_bytes = 0;
                info->stat_flags &= ~ESP_STAT_DMA_TX;
        }
 }
 
-static inline void check_modem_status(struct esp_struct *info)
+static void check_modem_status(struct esp_struct *info)
 {
        int     status;
-       
+
        serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);
        status = serial_in(info, UART_ESI_STAT2);
 
@@ -588,7 +579,7 @@ static inline void check_modem_status(struct esp_struct *info)
 #if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
                printk("ttys%d CD now %s...", info->line,
                       (status & UART_MSR_DCD) ? "on" : "off");
-#endif         
+#endif
                if (status & UART_MSR_DCD)
                        wake_up_interruptible(&info->open_wait);
                else {
@@ -605,7 +596,7 @@ static inline void check_modem_status(struct esp_struct *info)
  */
 static irqreturn_t rs_interrupt_single(int irq, void *dev_id)
 {
-       struct esp_struct * info;
+       struct esp_struct *info;
        unsigned err_status;
        unsigned int scratch;
 
@@ -617,7 +608,7 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id)
        scratch = serial_in(info, UART_ESI_SID);
 
        spin_lock(&info->lock);
-       
+
        if (!info->tty) {
                spin_unlock(&info->lock);
                return IRQ_NONE;
@@ -637,7 +628,7 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id)
                if (err_status & 0x80) /* Start break */
                        wake_up_interruptible(&info->break_wait);
        }
-               
+
        if ((scratch & 0x88) || /* DMA completed or timed out */
            (err_status & 0x1c) /* receive error */) {
                if (info->stat_flags & ESP_STAT_DMA_RX)
@@ -667,7 +658,7 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id)
                                receive_chars_dma(info, num_bytes);
                }
        }
-       
+
        if (!(info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) &&
            (scratch & 0x02) && (info->IER & UART_IER_THRI)) {
                if ((info->xmit_cnt <= 0) || info->tty->stopped) {
@@ -722,11 +713,11 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id)
  * ---------------------------------------------------------------
  */
 
-static inline void esp_basic_init(struct esp_struct * info)
+static void esp_basic_init(struct esp_struct *info)
 {
        /* put ESPC in enhanced mode */
        serial_out(info, UART_ESI_CMD1, ESI_SET_MODE);
-       
+
        if (info->stat_flags & ESP_STAT_NEVER_DMA)
                serial_out(info, UART_ESI_CMD2, 0x01);
        else
@@ -783,13 +774,13 @@ static inline void esp_basic_init(struct esp_struct * info)
        serial_out(info, UART_ESI_CMD2, 0xff);
 }
 
-static int startup(struct esp_struct * info)
+static int startup(struct esp_struct *info)
 {
        unsigned long flags;
-       int     retval=0;
-        unsigned int num_chars;
+       int     retval = 0;
+       unsigned int num_chars;
 
-        spin_lock_irqsave(&info->lock, flags);
+       spin_lock_irqsave(&info->lock, flags);
 
        if (info->flags & ASYNC_INITIALIZED)
                goto out;
@@ -802,7 +793,8 @@ static int startup(struct esp_struct * info)
        }
 
 #ifdef SERIAL_DEBUG_OPEN
-       printk("starting up ttys%d (irq %d)...", info->line, info->irq);
+       printk(KERN_DEBUG "starting up ttys%d (irq %d)...",
+                                               info->line, info->irq);
 #endif
 
        /* Flush the RX buffer.  Using the ESI flush command may cause */
@@ -863,7 +855,7 @@ static int startup(struct esp_struct * info)
                        dma_buffer = NULL;
                        info->stat_flags |= ESP_STAT_USE_PIO;
                }
-                       
+
        }
 
        info->MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
@@ -872,7 +864,7 @@ static int startup(struct esp_struct * info)
        serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
        serial_out(info, UART_ESI_CMD2, UART_MCR);
        serial_out(info, UART_ESI_CMD2, info->MCR);
-       
+
        /*
         * Finally, enable interrupts
         */
@@ -881,7 +873,7 @@ static int startup(struct esp_struct * info)
                        UART_IER_DMA_TC;
        serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
        serial_out(info, UART_ESI_CMD2, info->IER);
-       
+
        if (info->tty)
                clear_bit(TTY_IO_ERROR, &info->tty->flags);
        info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
@@ -900,7 +892,7 @@ static int startup(struct esp_struct * info)
                if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
                        info->tty->alt_speed = 460800;
        }
-       
+
        /*
         * set the speed of the serial port
         */
@@ -918,7 +910,7 @@ out_unlocked:
  * This routine will shutdown a serial port; interrupts are disabled, and
  * DTR is dropped if the hangup on close termio flag is on.
  */
-static void shutdown(struct esp_struct * info)
+static void shutdown(struct esp_struct *info)
 {
        unsigned long   flags, f;
 
@@ -929,7 +921,7 @@ static void shutdown(struct esp_struct * info)
        printk("Shutting down serial port %d (irq %d)....", info->line,
               info->irq);
 #endif
-       
+
        spin_lock_irqsave(&info->lock, flags);
        /*
         * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
@@ -941,14 +933,14 @@ static void shutdown(struct esp_struct * info)
        /* stop a DMA transfer on the port being closed */
        /* DMA lock is higher priority always */
        if (info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) {
-               f=claim_dma_lock();
+               f = claim_dma_lock();
                disable_dma(dma);
                clear_dma_ff(dma);
                release_dma_lock(f);
-               
+
                dma_bytes = 0;
        }
-       
+
        /*
         * Free the IRQ
         */
@@ -970,7 +962,7 @@ static void shutdown(struct esp_struct * info)
                        free_pages((unsigned long)dma_buffer,
                                   get_order(DMA_BUFFER_SZ));
                        dma_buffer = NULL;
-               }               
+               }
        }
 
        if (info->xmit_buf) {
@@ -992,7 +984,7 @@ static void shutdown(struct esp_struct * info)
 
        if (info->tty)
                set_bit(TTY_IO_ERROR, &info->tty->flags);
-       
+
        info->flags &= ~ASYNC_INITIALIZED;
        spin_unlock_irqrestore(&info->lock, flags);
 }
@@ -1005,7 +997,7 @@ static void change_speed(struct esp_struct *info)
 {
        unsigned short port;
        int     quot = 0;
-       unsigned cflag,cval;
+       unsigned cflag, cval;
        int     baud, bits;
        unsigned char flow1 = 0, flow2 = 0;
        unsigned long flags;
@@ -1014,14 +1006,14 @@ static void change_speed(struct esp_struct *info)
                return;
        cflag = info->tty->termios->c_cflag;
        port = info->port;
-       
+
        /* byte size and parity */
        switch (cflag & CSIZE) {
-             case CS5: cval = 0x00; bits = 7; break;
-             case CS6: cval = 0x01; bits = 8; break;
-             case CS7: cval = 0x02; bits = 9; break;
-             case CS8: cval = 0x03; bits = 10; break;
-             default:  cval = 0x00; bits = 7; break;
+       case CS5: cval = 0x00; bits = 7; break;
+       case CS6: cval = 0x01; bits = 8; break;
+       case CS7: cval = 0x02; bits = 9; break;
+       case CS8: cval = 0x03; bits = 10; break;
+       default:  cval = 0x00; bits = 7; break;
        }
        if (cflag & CSTOPB) {
                cval |= 0x04;
@@ -1037,14 +1029,12 @@ static void change_speed(struct esp_struct *info)
        if (cflag & CMSPAR)
                cval |= UART_LCR_SPAR;
 #endif
-
        baud = tty_get_baud_rate(info->tty);
        if (baud == 38400 &&
-           ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
+               ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
                quot = info->custom_divisor;
        else {
-               if (baud == 134)
-                       /* Special case since 134 is really 134.5 */
+               if (baud == 134) /* Special case since 134 is really 134.5 */
                        quot = (2*BASE_BAUD / 269);
                else if (baud)
                        quot = BASE_BAUD / baud;
@@ -1052,7 +1042,12 @@ static void change_speed(struct esp_struct *info)
        /* If the quotient is ever zero, default to 9600 bps */
        if (!quot)
                quot = BASE_BAUD / 9600;
-       
+
+       if (baud) {
+               /* Actual rate */
+               baud = BASE_BAUD/quot;
+               tty_encode_baud_rate(info->tty, baud, baud);
+       }
        info->timeout = ((1024 * HZ * bits * quot) / BASE_BAUD) + (HZ / 50);
 
        /* CTS flow control flag and modem status interrupts */
@@ -1066,10 +1061,8 @@ static void change_speed(struct esp_struct *info)
                info->flags &= ~ASYNC_CTS_FLOW;
        if (cflag & CLOCAL)
                info->flags &= ~ASYNC_CHECK_CD;
-       else {
+       else
                info->flags |= ASYNC_CHECK_CD;
-               /* info->IER |= UART_IER_MSI; */
-       }
 
        /*
         * Set up parity check flag
@@ -1079,7 +1072,7 @@ static void change_speed(struct esp_struct *info)
                info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
        if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
                info->read_status_mask |= UART_LSR_BI;
-       
+
        info->ignore_status_mask = 0;
 #if 0
        /* This should be safe, but for some broken bits of hardware... */
@@ -1092,7 +1085,7 @@ static void change_speed(struct esp_struct *info)
                info->ignore_status_mask |= UART_LSR_BI;
                info->read_status_mask |= UART_LSR_BI;
                /*
-                * If we're ignore parity and break indicators, ignore 
+                * If we're ignore parity and break indicators, ignore
                 * overruns too.  (For real raw support).
                 */
                if (I_IGNPAR(info->tty)) {
@@ -1130,19 +1123,19 @@ static void change_speed(struct esp_struct *info)
                serial_out(info, UART_ESI_CMD2, 0x10);
                serial_out(info, UART_ESI_CMD2, 0x21);
                switch (cflag & CSIZE) {
-                       case CS5:
-                               serial_out(info, UART_ESI_CMD2, 0x1f);
-                               break;
-                       case CS6:
-                               serial_out(info, UART_ESI_CMD2, 0x3f);
-                               break;
-                       case CS7:
-                       case CS8:
-                               serial_out(info, UART_ESI_CMD2, 0x7f);
-                               break;
-                       default:
-                               serial_out(info, UART_ESI_CMD2, 0xff);
-                               break;
+               case CS5:
+                       serial_out(info, UART_ESI_CMD2, 0x1f);
+                       break;
+               case CS6:
+                       serial_out(info, UART_ESI_CMD2, 0x3f);
+                       break;
+               case CS7:
+               case CS8:
+                       serial_out(info, UART_ESI_CMD2, 0x7f);
+                       break;
+               default:
+                       serial_out(info, UART_ESI_CMD2, 0xff);
+                       break;
                }
        }
 
@@ -1156,31 +1149,34 @@ static void change_speed(struct esp_struct *info)
        spin_unlock_irqrestore(&info->lock, flags);
 }
 
-static void rs_put_char(struct tty_struct *tty, unsigned char ch)
+static int rs_put_char(struct tty_struct *tty, unsigned char ch)
 {
-       struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+       struct esp_struct *info = tty->driver_data;
        unsigned long flags;
+       int ret = 0;
 
        if (serial_paranoia_check(info, tty->name, "rs_put_char"))
-               return;
+               return 0;
 
        if (!info->xmit_buf)
-               return;
+               return 0;
 
        spin_lock_irqsave(&info->lock, flags);
        if (info->xmit_cnt < ESP_XMIT_SIZE - 1) {
                info->xmit_buf[info->xmit_head++] = ch;
                info->xmit_head &= ESP_XMIT_SIZE-1;
                info->xmit_cnt++;
+               ret = 1;
        }
        spin_unlock_irqrestore(&info->lock, flags);
+       return ret;
 }
 
 static void rs_flush_chars(struct tty_struct *tty)
 {
-       struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+       struct esp_struct *info = tty->driver_data;
        unsigned long flags;
-                               
+
        if (serial_paranoia_check(info, tty->name, "rs_flush_chars"))
                return;
 
@@ -1198,11 +1194,11 @@ out:
        spin_unlock_irqrestore(&info->lock, flags);
 }
 
-static int rs_write(struct tty_struct * tty,
+static int rs_write(struct tty_struct *tty,
                    const unsigned char *buf, int count)
 {
        int     c, t, ret = 0;
-       struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+       struct esp_struct *info = tty->driver_data;
        unsigned long flags;
 
        if (serial_paranoia_check(info, tty->name, "rs_write"))
@@ -1210,19 +1206,19 @@ static int rs_write(struct tty_struct * tty,
 
        if (!info->xmit_buf)
                return 0;
-           
+
        while (1) {
                /* Thanks to R. Wolff for suggesting how to do this with */
                /* interrupts enabled */
 
                c = count;
                t = ESP_XMIT_SIZE - info->xmit_cnt - 1;
-               
+
                if (t < c)
                        c = t;
 
                t = ESP_XMIT_SIZE - info->xmit_head;
-               
+
                if (t < c)
                        c = t;
 
@@ -1252,10 +1248,10 @@ static int rs_write(struct tty_struct * tty,
 
 static int rs_write_room(struct tty_struct *tty)
 {
-       struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+       struct esp_struct *info = tty->driver_data;
        int     ret;
        unsigned long flags;
-                               
+
        if (serial_paranoia_check(info, tty->name, "rs_write_room"))
                return 0;
 
@@ -1270,8 +1266,8 @@ static int rs_write_room(struct tty_struct *tty)
 
 static int rs_chars_in_buffer(struct tty_struct *tty)
 {
-       struct esp_struct *info = (struct esp_struct *)tty->driver_data;
-                               
+       struct esp_struct *info = tty->driver_data;
+
        if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer"))
                return 0;
        return info->xmit_cnt;
@@ -1279,9 +1275,9 @@ static int rs_chars_in_buffer(struct tty_struct *tty)
 
 static void rs_flush_buffer(struct tty_struct *tty)
 {
-       struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+       struct esp_struct *info = tty->driver_data;
        unsigned long flags;
-                               
+
        if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
                return;
        spin_lock_irqsave(&info->lock, flags);
@@ -1293,20 +1289,20 @@ static void rs_flush_buffer(struct tty_struct *tty)
 /*
  * ------------------------------------------------------------
  * rs_throttle()
- * 
+ *
  * This routine is called by the upper-layer tty layer to signal that
  * incoming characters should be throttled.
  * ------------------------------------------------------------
  */
-static void rs_throttle(struct tty_struct * tty)
+static void rs_throttle(struct tty_struct *tty)
 {
-       struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+       struct esp_struct *info = tty->driver_data;
        unsigned long flags;
 #ifdef SERIAL_DEBUG_THROTTLE
        char    buf[64];
-       
+
        printk("throttle %s: %d....\n", tty_name(tty, buf),
-              tty->ldisc.chars_in_buffer(tty));
+                                               tty_chars_in_buffer(tty));
 #endif
 
        if (serial_paranoia_check(info, tty->name, "rs_throttle"))
@@ -1321,20 +1317,20 @@ static void rs_throttle(struct tty_struct * tty)
        spin_unlock_irqrestore(&info->lock, flags);
 }
 
-static void rs_unthrottle(struct tty_struct * tty)
+static void rs_unthrottle(struct tty_struct *tty)
 {
-       struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+       struct esp_struct *info = tty->driver_data;
        unsigned long flags;
 #ifdef SERIAL_DEBUG_THROTTLE
        char    buf[64];
-       
-       printk("unthrottle %s: %d....\n", tty_name(tty, buf),
-              tty->ldisc.chars_in_buffer(tty));
+
+       printk(KERN_DEBUG "unthrottle %s: %d....\n", tty_name(tty, buf),
+              tty_chars_in_buffer(tty));
 #endif
 
        if (serial_paranoia_check(info, tty->name, "rs_unthrottle"))
                return;
-       
+
        spin_lock_irqsave(&info->lock, flags);
        info->IER |= UART_IER_RDI;
        serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
@@ -1350,11 +1346,12 @@ static void rs_unthrottle(struct tty_struct * tty)
  * ------------------------------------------------------------
  */
 
-static int get_serial_info(struct esp_struct * info,
+static int get_serial_info(struct esp_struct *info,
                           struct serial_struct __user *retinfo)
 {
        struct serial_struct tmp;
-  
+
+       lock_kernel();
        memset(&tmp, 0, sizeof(tmp));
        tmp.type = PORT_16550A;
        tmp.line = info->line;
@@ -1367,20 +1364,22 @@ static int get_serial_info(struct esp_struct * info,
        tmp.closing_wait = info->closing_wait;
        tmp.custom_divisor = info->custom_divisor;
        tmp.hub6 = 0;
-       if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
+       unlock_kernel();
+       if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
                return -EFAULT;
        return 0;
 }
 
-static int get_esp_config(struct esp_struct * info,
+static int get_esp_config(struct esp_struct *info,
                          struct hayes_esp_config __user *retinfo)
 {
        struct hayes_esp_config tmp;
-  
+
        if (!retinfo)
                return -EFAULT;
 
        memset(&tmp, 0, sizeof(tmp));
+       lock_kernel();
        tmp.rx_timeout = info->config.rx_timeout;
        tmp.rx_trigger = info->config.rx_trigger;
        tmp.tx_trigger = info->config.tx_trigger;
@@ -1388,11 +1387,12 @@ static int get_esp_config(struct esp_struct * info,
        tmp.flow_on = info->config.flow_on;
        tmp.pio_threshold = info->config.pio_threshold;
        tmp.dma_channel = (info->stat_flags & ESP_STAT_NEVER_DMA ? 0 : dma);
+       unlock_kernel();
 
        return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
 }
 
-static int set_serial_info(struct esp_struct * info,
+static int set_serial_info(struct esp_struct *info,
                           struct serial_struct __user *new_info)
 {
        struct serial_struct new_serial;
@@ -1401,7 +1401,7 @@ static int set_serial_info(struct esp_struct * info,
        int retval = 0;
        struct esp_struct *current_async;
 
-       if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
+       if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
                return -EFAULT;
        old_info = *info;
 
@@ -1422,7 +1422,7 @@ static int set_serial_info(struct esp_struct * info,
                return -EINVAL;
 
        if (!capable(CAP_SYS_ADMIN)) {
-               if (change_irq || 
+               if (change_irq ||
                    (new_serial.close_delay != info->close_delay) ||
                    ((new_serial.flags & ~ASYNC_USR_MASK) !=
                     (info->flags & ~ASYNC_USR_MASK)))
@@ -1507,8 +1507,8 @@ static int set_serial_info(struct esp_struct * info,
        return retval;
 }
 
-static int set_esp_config(struct esp_struct * info,
-                         struct hayes_esp_config __user * new_info)
+static int set_esp_config(struct esp_struct *info,
+                         struct hayes_esp_config __user *new_info)
 {
        struct hayes_esp_config new_config;
        unsigned int change_dma;
@@ -1550,7 +1550,6 @@ static int set_esp_config(struct esp_struct * info,
                if (new_config.dma_channel) {
                        /* PIO mode to DMA mode transition OR */
                        /* change current DMA channel */
-                       
                        current_async = ports;
 
                        while (current_async) {
@@ -1559,16 +1558,15 @@ static int set_esp_config(struct esp_struct * info,
                                                return -EBUSY;
                                } else if (current_async->count)
                                        return -EBUSY;
-                                       
-                               current_async =
-                                       current_async->next_port;
+
+                               current_async = current_async->next_port;
                        }
 
                        shutdown(info);
                        dma = new_config.dma_channel;
                        info->stat_flags &= ~ESP_STAT_NEVER_DMA;
-                       
-                        /* all ports must use the same DMA channel */
+
+                       /* all ports must use the same DMA channel */
 
                        spin_lock_irqsave(&info->lock, flags);
                        current_async = ports;
@@ -1580,7 +1578,6 @@ static int set_esp_config(struct esp_struct * info,
                        spin_unlock_irqrestore(&info->lock, flags);
                } else {
                        /* DMA mode to PIO mode only */
-                       
                        if (info->count > 1)
                                return -EBUSY;
 
@@ -1596,8 +1593,6 @@ static int set_esp_config(struct esp_struct * info,
 
        if ((new_config.flow_off != info->config.flow_off) ||
            (new_config.flow_on != info->config.flow_on)) {
-               unsigned long flags;
-
                info->config.flow_off = new_config.flow_off;
                info->config.flow_on = new_config.flow_on;
 
@@ -1612,8 +1607,6 @@ static int set_esp_config(struct esp_struct * info,
 
        if ((new_config.rx_trigger != info->config.rx_trigger) ||
            (new_config.tx_trigger != info->config.tx_trigger)) {
-               unsigned long flags;
-
                info->config.rx_trigger = new_config.rx_trigger;
                info->config.tx_trigger = new_config.tx_trigger;
                spin_lock_irqsave(&info->lock, flags);
@@ -1628,8 +1621,6 @@ static int set_esp_config(struct esp_struct * info,
        }
 
        if (new_config.rx_timeout != info->config.rx_timeout) {
-               unsigned long flags;
-
                info->config.rx_timeout = new_config.rx_timeout;
                spin_lock_irqsave(&info->lock, flags);
 
@@ -1657,9 +1648,9 @@ static int set_esp_config(struct esp_struct * info,
  *         release the bus after transmitting. This must be done when
  *         the transmit shift register is empty, not be done when the
  *         transmit holding register is empty.  This functionality
- *         allows an RS485 driver to be written in user space. 
+ *         allows an RS485 driver to be written in user space.
  */
-static int get_lsr_info(struct esp_struct * info, unsigned int __user *value)
+static int get_lsr_info(struct esp_struct *info, unsigned int __user *value)
 {
        unsigned char status;
        unsigned int result;
@@ -1670,17 +1661,17 @@ static int get_lsr_info(struct esp_struct * info, unsigned int __user *value)
        status = serial_in(info, UART_ESI_STAT1);
        spin_unlock_irqrestore(&info->lock, flags);
        result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
-       return put_user(result,value);
+       return put_user(result, value);
 }
 
 
 static int esp_tiocmget(struct tty_struct *tty, struct file *file)
 {
-       struct esp_struct * info = (struct esp_struct *)tty->driver_data;
+       struct esp_struct *info = tty->driver_data;
        unsigned char control, status;
        unsigned long flags;
 
-       if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+       if (serial_paranoia_check(info, tty->name, __func__))
                return -ENODEV;
        if (tty->flags & (1 << TTY_IO_ERROR))
                return -EIO;
@@ -1703,10 +1694,10 @@ static int esp_tiocmget(struct tty_struct *tty, struct file *file)
 static int esp_tiocmset(struct tty_struct *tty, struct file *file,
                        unsigned int set, unsigned int clear)
 {
-       struct esp_struct * info = (struct esp_struct *)tty->driver_data;
+       struct esp_struct *info = tty->driver_data;
        unsigned long flags;
 
-       if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+       if (serial_paranoia_check(info, tty->name, __func__))
                return -ENODEV;
        if (tty->flags & (1 << TTY_IO_ERROR))
                return -EIO;
@@ -1736,9 +1727,9 @@ static int esp_tiocmset(struct tty_struct *tty, struct file *file,
  */
 static void esp_break(struct tty_struct *tty, int break_state)
 {
-       struct esp_struct * info = (struct esp_struct *)tty->driver_data;
+       struct esp_struct *info = tty->driver_data;
        unsigned long flags;
-       
+
        if (serial_paranoia_check(info, tty->name, "esp_break"))
                return;
 
@@ -1758,14 +1749,15 @@ static void esp_break(struct tty_struct *tty, int break_state)
        }
 }
 
-static int rs_ioctl(struct tty_struct *tty, struct file * file,
+static int rs_ioctl(struct tty_struct *tty, struct file *file,
                    unsigned int cmd, unsigned long arg)
 {
-       struct esp_struct * info = (struct esp_struct *)tty->driver_data;
+       struct esp_struct *info = tty->driver_data;
        struct async_icount cprev, cnow;        /* kernel counter temps */
        struct serial_icounter_struct __user *p_cuser;  /* user space */
        void __user *argp = (void __user *)arg;
        unsigned long flags;
+       int ret;
 
        if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
                return -ENODEV;
@@ -1778,97 +1770,93 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
                if (tty->flags & (1 << TTY_IO_ERROR))
                    return -EIO;
        }
-       
-       switch (cmd) {
-               case TIOCGSERIAL:
-                       return get_serial_info(info, argp);
-               case TIOCSSERIAL:
-                       return set_serial_info(info, argp);
-               case TIOCSERCONFIG:
-                       /* do not reconfigure after initial configuration */
-                       return 0;
-
-               case TIOCSERGWILD:
-                       return put_user(0L, (unsigned long __user *)argp);
 
-               case TIOCSERGETLSR: /* Get line status register */
-                           return get_lsr_info(info, argp);
-
-               case TIOCSERSWILD:
-                       if (!capable(CAP_SYS_ADMIN))
-                               return -EPERM;
-                       return 0;
-
-               /*
-                * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
-                * - mask passed in arg for lines of interest
-                *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
-                * Caller should use TIOCGICOUNT to see which one it was
-                */
-                case TIOCMIWAIT:
+       switch (cmd) {
+       case TIOCGSERIAL:
+               return get_serial_info(info, argp);
+       case TIOCSSERIAL:
+               lock_kernel();
+               ret = set_serial_info(info, argp);
+               unlock_kernel();
+               return ret;
+       case TIOCSERGWILD:
+               return put_user(0L, (unsigned long __user *)argp);
+       case TIOCSERGETLSR: /* Get line status register */
+               return get_lsr_info(info, argp);
+       case TIOCSERSWILD:
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+               return 0;
+       /*
+        * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+        * - mask passed in arg for lines of interest
+        *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+        * Caller should use TIOCGICOUNT to see which one it was
+        */
+       case TIOCMIWAIT:
+               spin_lock_irqsave(&info->lock, flags);
+               cprev = info->icount;   /* note the counters on entry */
+               spin_unlock_irqrestore(&info->lock, flags);
+               while (1) {
+                       /* FIXME: convert to new style wakeup */
+                       interruptible_sleep_on(&info->delta_msr_wait);
+                       /* see if a signal did it */
+                       if (signal_pending(current))
+                               return -ERESTARTSYS;
                        spin_lock_irqsave(&info->lock, flags);
-                       cprev = info->icount;   /* note the counters on entry */
+                       cnow = info->icount;    /* atomic copy */
                        spin_unlock_irqrestore(&info->lock, flags);
-                       while (1) {
-                               /* FIXME: convert to new style wakeup */
-                               interruptible_sleep_on(&info->delta_msr_wait);
-                               /* see if a signal did it */
-                               if (signal_pending(current))
-                                       return -ERESTARTSYS;
-                               spin_lock_irqsave(&info->lock, flags);
-                               cnow = info->icount;    /* atomic copy */
-                               spin_unlock_irqrestore(&info->lock, flags);
-                               if (cnow.rng == cprev.rng &&
-                                   cnow.dsr == cprev.dsr && 
-                                   cnow.dcd == cprev.dcd &&
-                                   cnow.cts == cprev.cts)
-                                       return -EIO; /* no change => error */
-                               if (((arg & TIOCM_RNG) &&
-                                    (cnow.rng != cprev.rng)) ||
-                                    ((arg & TIOCM_DSR) &&
-                                     (cnow.dsr != cprev.dsr)) ||
-                                    ((arg & TIOCM_CD) &&
-                                     (cnow.dcd != cprev.dcd)) ||
-                                    ((arg & TIOCM_CTS) &&
-                                     (cnow.cts != cprev.cts)) ) {
-                                       return 0;
-                               }
-                               cprev = cnow;
+                       if (cnow.rng == cprev.rng &&
+                           cnow.dsr == cprev.dsr &&
+                           cnow.dcd == cprev.dcd &&
+                           cnow.cts == cprev.cts)
+                               return -EIO; /* no change => error */
+                       if (((arg & TIOCM_RNG) &&
+                            (cnow.rng != cprev.rng)) ||
+                            ((arg & TIOCM_DSR) &&
+                             (cnow.dsr != cprev.dsr)) ||
+                            ((arg & TIOCM_CD) &&
+                             (cnow.dcd != cprev.dcd)) ||
+                            ((arg & TIOCM_CTS) &&
+                             (cnow.cts != cprev.cts))) {
+                               return 0;
                        }
-                       /* NOTREACHED */
-
-               /* 
-                * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-                * Return: write counters to the user passed counter struct
-                * NB: both 1->0 and 0->1 transitions are counted except for
-                *     RI where only 0->1 is counted.
-                */
-               case TIOCGICOUNT:
-                       spin_lock_irqsave(&info->lock, flags);
-                       cnow = info->icount;
-                       spin_unlock_irqrestore(&info->lock, flags);
-                       p_cuser = argp;
-                       if (put_user(cnow.cts, &p_cuser->cts) ||
-                           put_user(cnow.dsr, &p_cuser->dsr) ||
-                           put_user(cnow.rng, &p_cuser->rng) ||
-                           put_user(cnow.dcd, &p_cuser->dcd))
-                               return -EFAULT;
-
+                       cprev = cnow;
+               }
+               /* NOTREACHED */
+       /*
+        * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+        * Return: write counters to the user passed counter struct
+        * NB: both 1->0 and 0->1 transitions are counted except for
+        *     RI where only 0->1 is counted.
+        */
+       case TIOCGICOUNT:
+               spin_lock_irqsave(&info->lock, flags);
+               cnow = info->icount;
+               spin_unlock_irqrestore(&info->lock, flags);
+               p_cuser = argp;
+               if (put_user(cnow.cts, &p_cuser->cts) ||
+                   put_user(cnow.dsr, &p_cuser->dsr) ||
+                   put_user(cnow.rng, &p_cuser->rng) ||
+                   put_user(cnow.dcd, &p_cuser->dcd))
+                       return -EFAULT;
                        return 0;
        case TIOCGHAYESESP:
                return get_esp_config(info, argp);
        case TIOCSHAYESESP:
-               return set_esp_config(info, argp);
-
-               default:
-                       return -ENOIOCTLCMD;
-               }
+               lock_kernel();
+               ret = set_esp_config(info, argp);
+               unlock_kernel();
+               return ret;
+       default:
+               return -ENOIOCTLCMD;
+       }
        return 0;
 }
 
 static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
-       struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+       struct esp_struct *info = tty->driver_data;
        unsigned long flags;
 
        change_speed(info);
@@ -1905,32 +1893,33 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 /*
  * ------------------------------------------------------------
  * rs_close()
- * 
+ *
  * This routine is called when the serial port gets closed.  First, we
  * wait for the last remaining data to be sent.  Then, we unlink its
  * async structure from the interrupt chain if necessary, and we free
  * that IRQ if nothing is left in the chain.
  * ------------------------------------------------------------
  */
-static void rs_close(struct tty_struct *tty, struct file * filp)
+static void rs_close(struct tty_struct *tty, struct file *filp)
 {
-       struct esp_struct * info = (struct esp_struct *)tty->driver_data;
+       struct esp_struct *info = tty->driver_data;
        unsigned long flags;
 
        if (!info || serial_paranoia_check(info, tty->name, "rs_close"))
                return;
-       
+
        spin_lock_irqsave(&info->lock, flags);
-       
+
        if (tty_hung_up_p(filp)) {
                DBG_CNT("before DEC-hung");
                goto out;
        }
-       
+
 #ifdef SERIAL_DEBUG_OPEN
-       printk("rs_close ttys%d, count = %d\n", info->line, info->count);
+       printk(KERN_DEBUG "rs_close ttys%d, count = %d\n",
+                                               info->line, info->count);
 #endif
-       if ((tty->count == 1) && (info->count != 1)) {
+       if (tty->count == 1 && info->count != 1) {
                /*
                 * Uh, oh.  tty->count is 1, which means that the tty
                 * structure will be freed.  Info->count should always
@@ -1938,12 +1927,11 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
                 * one, we've got real problems, since it means the
                 * serial port won't be shutdown.
                 */
-               printk("rs_close: bad serial port count; tty->count is 1, "
-                      "info->count is %d\n", info->count);
+               printk(KERN_DEBUG "rs_close: bad serial port count; tty->count is 1, info->count is %d\n", info->count);
                info->count = 1;
        }
        if (--info->count < 0) {
-               printk("rs_close: bad serial port count for ttys%d: %d\n",
+               printk(KERN_ERR "rs_close: bad serial port count for ttys%d: %d\n",
                       info->line, info->count);
                info->count = 0;
        }
@@ -1955,7 +1943,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
 
        spin_unlock_irqrestore(&info->lock, flags);
        /*
-        * Now we wait for the transmit buffer to clear; and we notify 
+        * Now we wait for the transmit buffer to clear; and we notify
         * the line discipline to only process XON/XOFF characters.
         */
        tty->closing = 1;
@@ -1990,16 +1978,14 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
                rs_wait_until_sent(tty, info->timeout);
        }
        shutdown(info);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       rs_flush_buffer(tty);
        tty_ldisc_flush(tty);
        tty->closing = 0;
        info->tty = NULL;
 
        if (info->blocked_open) {
-               if (info->close_delay) {
+               if (info->close_delay)
                        msleep_interruptible(jiffies_to_msecs(info->close_delay));
-               }
                wake_up_interruptible(&info->open_wait);
        }
        info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
@@ -2012,7 +1998,7 @@ out:
 
 static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
 {
-       struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+       struct esp_struct *info = tty->driver_data;
        unsigned long orig_jiffies, char_time;
        unsigned long flags;
 
@@ -2036,10 +2022,10 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
                msleep_interruptible(jiffies_to_msecs(char_time));
 
                if (signal_pending(current))
-                       break;
+                       return;
 
                if (timeout && time_after(jiffies, orig_jiffies + timeout))
-                       break;
+                       return;
 
                spin_lock_irqsave(&info->lock, flags);
                serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
@@ -2054,11 +2040,11 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
  */
 static void esp_hangup(struct tty_struct *tty)
 {
-       struct esp_struct * info = (struct esp_struct *)tty->driver_data;
-       
+       struct esp_struct *info = tty->driver_data;
+
        if (serial_paranoia_check(info, tty->name, "esp_hangup"))
                return;
-       
+
        rs_flush_buffer(tty);
        shutdown(info);
        info->count = 0;
@@ -2072,7 +2058,7 @@ static void esp_hangup(struct tty_struct *tty)
  * esp_open() and friends
  * ------------------------------------------------------------
  */
-static int block_til_ready(struct tty_struct *tty, struct file * filp,
+static int block_til_ready(struct tty_struct *tty, struct file *filp,
                           struct esp_struct *info)
 {
        DECLARE_WAITQUEUE(wait, current);
@@ -2121,11 +2107,11 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
        retval = 0;
        add_wait_queue(&info->open_wait, &wait);
 #ifdef SERIAL_DEBUG_OPEN
-       printk("block_til_ready before block: ttys%d, count = %d\n",
+       printk(KERN_DEBUG "block_til_ready before block: ttys%d, count = %d\n",
               info->line, info->count);
 #endif
        spin_lock_irqsave(&info->lock, flags);
-       if (!tty_hung_up_p(filp)) 
+       if (!tty_hung_up_p(filp))
                info->count--;
        info->blocked_open++;
        while (1) {
@@ -2147,7 +2133,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
                        if (info->flags & ASYNC_HUP_NOTIFY)
                                retval = -EAGAIN;
                        else
-                               retval = -ERESTARTSYS;  
+                               retval = -ERESTARTSYS;
 #else
                        retval = -EAGAIN;
 #endif
@@ -2166,7 +2152,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
                        break;
                }
 #ifdef SERIAL_DEBUG_OPEN
-               printk("block_til_ready blocking: ttys%d, count = %d\n",
+               printk(KERN_DEBUG "block_til_ready blocking: ttys%d, count = %d\n",
                       info->line, info->count);
 #endif
                spin_unlock_irqrestore(&info->lock, flags);
@@ -2180,14 +2166,14 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
        info->blocked_open--;
        spin_unlock_irqrestore(&info->lock, flags);
 #ifdef SERIAL_DEBUG_OPEN
-       printk("block_til_ready after blocking: ttys%d, count = %d\n",
+       printk(KERN_DEBUG "block_til_ready after blocking: ttys%d, count = %d\n",
               info->line, info->count);
 #endif
        if (retval)
                return retval;
        info->flags |= ASYNC_NORMAL_ACTIVE;
        return 0;
-}      
+}
 
 /*
  * This routine is called whenever a serial port is opened.  It
@@ -2195,7 +2181,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
  * the IRQ chain.   It also performs the serial-specific
  * initialization for the tty structure.
  */
-static int esp_open(struct tty_struct *tty, struct file * filp)
+static int esp_open(struct tty_struct *tty, struct file *filp)
 {
        struct esp_struct       *info;
        int                     retval, line;
@@ -2218,7 +2204,7 @@ static int esp_open(struct tty_struct *tty, struct file * filp)
        }
 
 #ifdef SERIAL_DEBUG_OPEN
-       printk("esp_open %s, count = %d\n", tty->name, info->count);
+       printk(KERN_DEBUG "esp_open %s, count = %d\n", tty->name, info->count);
 #endif
        spin_lock_irqsave(&info->lock, flags);
        info->count++;
@@ -2226,7 +2212,7 @@ static int esp_open(struct tty_struct *tty, struct file * filp)
        info->tty = tty;
 
        spin_unlock_irqrestore(&info->lock, flags);
-       
+
        /*
         * Start up serial port
         */
@@ -2237,14 +2223,13 @@ static int esp_open(struct tty_struct *tty, struct file * filp)
        retval = block_til_ready(tty, filp, info);
        if (retval) {
 #ifdef SERIAL_DEBUG_OPEN
-               printk("esp_open returning after block_til_ready with %d\n",
+               printk(KERN_DEBUG "esp_open returning after block_til_ready with %d\n",
                       retval);
 #endif
                return retval;
        }
-
 #ifdef SERIAL_DEBUG_OPEN
-       printk("esp_open %s successful...", tty->name);
+       printk(KERN_DEBUG "esp_open %s successful...", tty->name);
 #endif
        return 0;
 }
@@ -2262,10 +2247,10 @@ static int esp_open(struct tty_struct *tty, struct file * filp)
  * number, and identifies which options were configured into this
  * driver.
  */
-static inline void show_serial_version(void)
+
+static void show_serial_version(void)
 {
-       printk(KERN_INFO "%s version %s (DMA %u)\n",
+       printk(KERN_INFO "%s version %s (DMA %u)\n",
                serial_name, serial_version, dma);
 }
 
@@ -2273,7 +2258,7 @@ static inline void show_serial_version(void)
  * This routine is called by espserial_init() to initialize a specific serial
  * port.
  */
-static inline int autoconfig(struct esp_struct * info)
+static int autoconfig(struct esp_struct *info)
 {
        int port_detected = 0;
        unsigned long flags;
@@ -2349,14 +2334,14 @@ static const struct tty_operations esp_ops = {
 static int __init espserial_init(void)
 {
        int i, offset;
-       struct esp_struct * info;
+       struct esp_struct *info;
        struct esp_struct *last_primary = NULL;
-       int esp[] = {0x100,0x140,0x180,0x200,0x240,0x280,0x300,0x380};
+       int esp[] = { 0x100, 0x140, 0x180, 0x200, 0x240, 0x280, 0x300, 0x380 };
 
        esp_driver = alloc_tty_driver(NR_PORTS);
        if (!esp_driver)
                return -ENOMEM;
-       
+
        for (i = 0; i < NR_PRIMARY; i++) {
                if (irq[i] != 0) {
                        if ((irq[i] < 2) || (irq[i] > 15) || (irq[i] == 6) ||
@@ -2378,20 +2363,20 @@ static int __init espserial_init(void)
 
        if ((flow_off < 1) || (flow_off > 1023))
                flow_off = 1016;
-       
+
        if ((flow_on < 1) || (flow_on > 1023))
                flow_on = 944;
 
        if ((rx_timeout < 0) || (rx_timeout > 255))
                rx_timeout = 128;
-       
+
        if (flow_on >= flow_off)
                flow_on = flow_off - 1;
 
        show_serial_version();
 
        /* Initialize the tty_driver structure */
-       
+
        esp_driver->owner = THIS_MODULE;
        esp_driver->name = "ttyP";
        esp_driver->major = ESP_IN_MAJOR;
@@ -2401,10 +2386,11 @@ static int __init espserial_init(void)
        esp_driver->init_termios = tty_std_termios;
        esp_driver->init_termios.c_cflag =
                B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+       esp_driver->init_termios.c_ispeed = 9600;
+       esp_driver->init_termios.c_ospeed = 9600;
        esp_driver->flags = TTY_DRIVER_REAL_RAW;
        tty_set_operations(esp_driver, &esp_ops);
-       if (tty_register_driver(esp_driver))
-       {
+       if (tty_register_driver(esp_driver)) {
                printk(KERN_ERR "Couldn't register esp serial driver");
                put_tty_driver(esp_driver);
                return 1;
@@ -2412,8 +2398,7 @@ static int __init espserial_init(void)
 
        info = kzalloc(sizeof(struct esp_struct), GFP_KERNEL);
 
-       if (!info)
-       {
+       if (!info) {
                printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n");
                tty_unregister_driver(esp_driver);
                put_tty_driver(esp_driver);
@@ -2476,10 +2461,8 @@ static int __init espserial_init(void)
                        info->stat_flags |= ESP_STAT_NEVER_DMA;
 
                info = kzalloc(sizeof(struct esp_struct), GFP_KERNEL);
-               if (!info)
-               {
-                       printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n"); 
-
+               if (!info) {
+                       printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n");
                        /* allow use of the already detected ports */
                        return 0;
                }
@@ -2503,22 +2486,20 @@ static int __init espserial_init(void)
        return 0;
 }
 
-static void __exit espserial_exit(void) 
+static void __exit espserial_exit(void)
 {
        int e1;
        struct esp_struct *temp_async;
        struct esp_pio_buffer *pio_buf;
 
-       /* printk("Unloading %s: version %s\n", serial_name, serial_version); */
-       if ((e1 = tty_unregister_driver(esp_driver)))
-               printk("SERIAL: failed to unregister serial driver (%d)\n",
-                      e1);
+       e1 = tty_unregister_driver(esp_driver);
+       if (e1)
+               printk(KERN_ERR "esp: failed to unregister driver (%d)\n", e1);
        put_tty_driver(esp_driver);
 
        while (ports) {
-               if (ports->port) {
+               if (ports->port)
                        release_region(ports->port, REGION_SIZE);
-               }
                temp_async = ports->next_port;
                kfree(ports);
                ports = temp_async;
index 7ed7da1d99cf9120f238601e794df7845992ff2a..252f73e4859664b79bcb32657445265d943c10bb 100644 (file)
@@ -40,27 +40,27 @@ static int gs_debug;
 #define gs_dprintk(f, str...) /* nothing */
 #endif
 
-#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __FUNCTION__)
-#define func_exit()  gs_dprintk (GS_DEBUG_FLOW, "gs: exit  %s\n", __FUNCTION__)
+#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __func__)
+#define func_exit()  gs_dprintk (GS_DEBUG_FLOW, "gs: exit  %s\n", __func__)
 
 #define RS_EVENT_WRITE_WAKEUP  1
 
 module_param(gs_debug, int, 0644);
 
 
-void gs_put_char(struct tty_struct * tty, unsigned char ch)
+int gs_put_char(struct tty_struct * tty, unsigned char ch)
 {
        struct gs_port *port;
 
        func_enter (); 
 
-       if (!tty) return;
+       if (!tty) return 0;
 
        port = tty->driver_data;
 
-       if (!port) return;
+       if (!port) return 0;
 
-       if (! (port->flags & ASYNC_INITIALIZED)) return;
+       if (! (port->flags & ASYNC_INITIALIZED)) return 0;
 
        /* Take a lock on the serial tranmit buffer! */
        mutex_lock(& port->port_write_mutex);
@@ -68,7 +68,7 @@ void gs_put_char(struct tty_struct * tty, unsigned char ch)
        if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
                /* Sorry, buffer is full, drop character. Update statistics???? -- REW */
                mutex_unlock(&port->port_write_mutex);
-               return;
+               return 0;
        }
 
        port->xmit_buf[port->xmit_head++] = ch;
@@ -77,6 +77,7 @@ void gs_put_char(struct tty_struct * tty, unsigned char ch)
 
        mutex_unlock(&port->port_write_mutex);
        func_exit ();
+       return 1;
 }
 
 
@@ -586,8 +587,7 @@ void gs_close(struct tty_struct * tty, struct file * filp)
 
        port->flags &= ~GS_ACTIVE;
 
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       gs_flush_buffer(tty);
 
        tty_ldisc_flush(tty);
        tty->closing = 0;
index 1399971be6890c2167aea675a51b77bfce3f41d5..e7fb0bca3667670f27ae781893bab44b6f51d006 100644 (file)
@@ -308,7 +308,7 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
        if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
                                        PAGE_SIZE, vma->vm_page_prot)) {
                printk(KERN_ERR "%s: io_remap_pfn_range failed\n",
-                       __FUNCTION__);
+                       __func__);
                return -EAGAIN;
        }
 
@@ -748,7 +748,7 @@ int hpet_alloc(struct hpet_data *hdp)
         */
        if (hpet_is_known(hdp)) {
                printk(KERN_DEBUG "%s: duplicate HPET ignored\n",
-                       __FUNCTION__);
+                       __func__);
                return 0;
        }
 
@@ -869,7 +869,7 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
 
                if (hpet_is_known(hdp)) {
                        printk(KERN_DEBUG "%s: 0x%lx is busy\n",
-                               __FUNCTION__, hdp->hd_phys_address);
+                               __func__, hdp->hd_phys_address);
                        iounmap(hdp->hd_address);
                        return AE_ALREADY_EXISTS;
                }
@@ -886,7 +886,7 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
 
                if (hpet_is_known(hdp)) {
                        printk(KERN_DEBUG "%s: 0x%lx is busy\n",
-                               __FUNCTION__, hdp->hd_phys_address);
+                               __func__, hdp->hd_phys_address);
                        iounmap(hdp->hd_address);
                        return AE_ALREADY_EXISTS;
                }
@@ -925,7 +925,7 @@ static int hpet_acpi_add(struct acpi_device *device)
                return -ENODEV;
 
        if (!data.hd_address || !data.hd_nirqs) {
-               printk("%s: no address or irqs in _CRS\n", __FUNCTION__);
+               printk("%s: no address or irqs in _CRS\n", __func__);
                return -ENODEV;
        }
 
index d5a752da322f855261a06c9aacb93636fb57d1f9..59c6f9ab94e4b279700ff1f50f1f39ae02b54fa2 100644 (file)
@@ -246,7 +246,7 @@ static void compact_inbuf(struct hvsi_struct *hp, uint8_t *read_to)
 {
        int remaining = (int)(hp->inbuf_end - read_to);
 
-       pr_debug("%s: %i chars remain\n", __FUNCTION__, remaining);
+       pr_debug("%s: %i chars remain\n", __func__, remaining);
 
        if (read_to != hp->inbuf)
                memmove(hp->inbuf, read_to, remaining);
@@ -365,7 +365,7 @@ static int hvsi_version_respond(struct hvsi_struct *hp, uint16_t query_seqno)
        packet.u.version = HVSI_VERSION;
        packet.query_seqno = query_seqno+1;
 
-       pr_debug("%s: sending %i bytes\n", __FUNCTION__, packet.len);
+       pr_debug("%s: sending %i bytes\n", __func__, packet.len);
        dbg_dump_hex((uint8_t*)&packet, packet.len);
 
        wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
@@ -437,7 +437,7 @@ static struct tty_struct *hvsi_recv_data(struct hvsi_struct *hp,
                return NULL;
 
        if (overflow > 0) {
-               pr_debug("%s: got >TTY_THRESHOLD_THROTTLE bytes\n", __FUNCTION__);
+               pr_debug("%s: got >TTY_THRESHOLD_THROTTLE bytes\n", __func__);
                datalen = TTY_THRESHOLD_THROTTLE;
        }
 
@@ -448,7 +448,7 @@ static struct tty_struct *hvsi_recv_data(struct hvsi_struct *hp,
                 * we still have more data to deliver, so we need to save off the
                 * overflow and send it later
                 */
-               pr_debug("%s: deferring overflow\n", __FUNCTION__);
+               pr_debug("%s: deferring overflow\n", __func__);
                memcpy(hp->throttle_buf, data + TTY_THRESHOLD_THROTTLE, overflow);
                hp->n_throttle = overflow;
        }
@@ -474,11 +474,11 @@ static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct **flip,
 
        chunklen = hvsi_read(hp, hp->inbuf_end, HVSI_MAX_READ);
        if (chunklen == 0) {
-               pr_debug("%s: 0-length read\n", __FUNCTION__);
+               pr_debug("%s: 0-length read\n", __func__);
                return 0;
        }
 
-       pr_debug("%s: got %i bytes\n", __FUNCTION__, chunklen);
+       pr_debug("%s: got %i bytes\n", __func__, chunklen);
        dbg_dump_hex(hp->inbuf_end, chunklen);
 
        hp->inbuf_end += chunklen;
@@ -495,7 +495,7 @@ static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct **flip,
                        continue;
                }
 
-               pr_debug("%s: handling %i-byte packet\n", __FUNCTION__,
+               pr_debug("%s: handling %i-byte packet\n", __func__,
                                len_packet(packet));
                dbg_dump_packet(packet);
 
@@ -526,7 +526,7 @@ static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct **flip,
                packet += len_packet(packet);
 
                if (*hangup || *handshake) {
-                       pr_debug("%s: hangup or handshake\n", __FUNCTION__);
+                       pr_debug("%s: hangup or handshake\n", __func__);
                        /*
                         * we need to send the hangup now before receiving any more data.
                         * If we get "data, hangup, data", we can't deliver the second
@@ -543,7 +543,7 @@ static int hvsi_load_chunk(struct hvsi_struct *hp, struct tty_struct **flip,
 
 static void hvsi_send_overflow(struct hvsi_struct *hp)
 {
-       pr_debug("%s: delivering %i bytes overflow\n", __FUNCTION__,
+       pr_debug("%s: delivering %i bytes overflow\n", __func__,
                        hp->n_throttle);
 
        hvsi_insert_chars(hp, hp->throttle_buf, hp->n_throttle);
@@ -563,7 +563,7 @@ static irqreturn_t hvsi_interrupt(int irq, void *arg)
        unsigned long flags;
        int again = 1;
 
-       pr_debug("%s\n", __FUNCTION__);
+       pr_debug("%s\n", __func__);
 
        while (again) {
                spin_lock_irqsave(&hp->lock, flags);
@@ -647,7 +647,7 @@ static int hvsi_query(struct hvsi_struct *hp, uint16_t verb)
        packet.seqno = atomic_inc_return(&hp->seqno);
        packet.verb = verb;
 
-       pr_debug("%s: sending %i bytes\n", __FUNCTION__, packet.len);
+       pr_debug("%s: sending %i bytes\n", __func__, packet.len);
        dbg_dump_hex((uint8_t*)&packet, packet.len);
 
        wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
@@ -674,7 +674,7 @@ static int hvsi_get_mctrl(struct hvsi_struct *hp)
                return ret;
        }
 
-       pr_debug("%s: mctrl 0x%x\n", __FUNCTION__, hp->mctrl);
+       pr_debug("%s: mctrl 0x%x\n", __func__, hp->mctrl);
 
        return 0;
 }
@@ -694,7 +694,7 @@ static int hvsi_set_mctrl(struct hvsi_struct *hp, uint16_t mctrl)
        if (mctrl & TIOCM_DTR)
                packet.word = HVSI_TSDTR;
 
-       pr_debug("%s: sending %i bytes\n", __FUNCTION__, packet.len);
+       pr_debug("%s: sending %i bytes\n", __func__, packet.len);
        dbg_dump_hex((uint8_t*)&packet, packet.len);
 
        wrote = hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
@@ -790,7 +790,7 @@ static void hvsi_close_protocol(struct hvsi_struct *hp)
        packet.len = 6;
        packet.verb = VSV_CLOSE_PROTOCOL;
 
-       pr_debug("%s: sending %i bytes\n", __FUNCTION__, packet.len);
+       pr_debug("%s: sending %i bytes\n", __func__, packet.len);
        dbg_dump_hex((uint8_t*)&packet, packet.len);
 
        hvc_put_chars(hp->vtermno, (char *)&packet, packet.len);
@@ -803,7 +803,7 @@ static int hvsi_open(struct tty_struct *tty, struct file *filp)
        int line = tty->index;
        int ret;
 
-       pr_debug("%s\n", __FUNCTION__);
+       pr_debug("%s\n", __func__);
 
        if (line < 0 || line >= hvsi_count)
                return -ENODEV;
@@ -868,7 +868,7 @@ static void hvsi_close(struct tty_struct *tty, struct file *filp)
        struct hvsi_struct *hp = tty->driver_data;
        unsigned long flags;
 
-       pr_debug("%s\n", __FUNCTION__);
+       pr_debug("%s\n", __func__);
 
        if (tty_hung_up_p(filp))
                return;
@@ -920,7 +920,7 @@ static void hvsi_hangup(struct tty_struct *tty)
        struct hvsi_struct *hp = tty->driver_data;
        unsigned long flags;
 
-       pr_debug("%s\n", __FUNCTION__);
+       pr_debug("%s\n", __func__);
 
        spin_lock_irqsave(&hp->lock, flags);
 
@@ -942,7 +942,7 @@ static void hvsi_push(struct hvsi_struct *hp)
        n = hvsi_put_chars(hp, hp->outbuf, hp->n_outbuf);
        if (n > 0) {
                /* success */
-               pr_debug("%s: wrote %i chars\n", __FUNCTION__, n);
+               pr_debug("%s: wrote %i chars\n", __func__, n);
                hp->n_outbuf = 0;
        } else if (n == -EIO) {
                __set_state(hp, HVSI_FSP_DIED);
@@ -965,7 +965,7 @@ static void hvsi_write_worker(struct work_struct *work)
 
        spin_lock_irqsave(&hp->lock, flags);
 
-       pr_debug("%s: %i chars in buffer\n", __FUNCTION__, hp->n_outbuf);
+       pr_debug("%s: %i chars in buffer\n", __func__, hp->n_outbuf);
 
        if (!is_open(hp)) {
                /*
@@ -983,7 +983,7 @@ static void hvsi_write_worker(struct work_struct *work)
                schedule_delayed_work(&hp->writer, 10);
        else {
 #ifdef DEBUG
-               pr_debug("%s: outbuf emptied after %li jiffies\n", __FUNCTION__,
+               pr_debug("%s: outbuf emptied after %li jiffies\n", __func__,
                                jiffies - start_j);
                start_j = 0;
 #endif /* DEBUG */
@@ -1020,11 +1020,11 @@ static int hvsi_write(struct tty_struct *tty,
 
        spin_lock_irqsave(&hp->lock, flags);
 
-       pr_debug("%s: %i chars in buffer\n", __FUNCTION__, hp->n_outbuf);
+       pr_debug("%s: %i chars in buffer\n", __func__, hp->n_outbuf);
 
        if (!is_open(hp)) {
                /* we're either closing or not yet open; don't accept data */
-               pr_debug("%s: not open\n", __FUNCTION__);
+               pr_debug("%s: not open\n", __func__);
                goto out;
        }
 
@@ -1058,7 +1058,7 @@ out:
        spin_unlock_irqrestore(&hp->lock, flags);
 
        if (total != origcount)
-               pr_debug("%s: wanted %i, only wrote %i\n", __FUNCTION__, origcount,
+               pr_debug("%s: wanted %i, only wrote %i\n", __func__, origcount,
                        total);
 
        return total;
@@ -1072,7 +1072,7 @@ static void hvsi_throttle(struct tty_struct *tty)
 {
        struct hvsi_struct *hp = (struct hvsi_struct *)tty->driver_data;
 
-       pr_debug("%s\n", __FUNCTION__);
+       pr_debug("%s\n", __func__);
 
        h_vio_signal(hp->vtermno, VIO_IRQ_DISABLE);
 }
@@ -1083,7 +1083,7 @@ static void hvsi_unthrottle(struct tty_struct *tty)
        unsigned long flags;
        int shouldflip = 0;
 
-       pr_debug("%s\n", __FUNCTION__);
+       pr_debug("%s\n", __func__);
 
        spin_lock_irqsave(&hp->lock, flags);
        if (hp->n_throttle) {
@@ -1302,7 +1302,7 @@ static int __init hvsi_console_init(void)
                hp->virq = irq_create_mapping(NULL, irq[0]);
                if (hp->virq == NO_IRQ) {
                        printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n",
-                               __FUNCTION__, irq[0]);
+                               __func__, irq[0]);
                        continue;
                }
 
index 8609b8236c67d42562ada21812b3c757534166b6..f49037b744f99ef52455bfad7588f5d1610b7c35 100644 (file)
@@ -82,6 +82,7 @@ static int i8k_ioctl(struct inode *, struct file *, unsigned int,
                     unsigned long);
 
 static const struct file_operations i8k_fops = {
+       .owner          = THIS_MODULE,
        .open           = i8k_open_fs,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -554,13 +555,10 @@ static int __init i8k_init(void)
                return -ENODEV;
 
        /* Register the proc entry */
-       proc_i8k = create_proc_entry("i8k", 0, NULL);
+       proc_i8k = proc_create("i8k", 0, NULL, &i8k_fops);
        if (!proc_i8k)
                return -ENOENT;
 
-       proc_i8k->proc_fops = &i8k_fops;
-       proc_i8k->owner = THIS_MODULE;
-
        printk(KERN_INFO
               "Dell laptop SMM driver v%s Massimo Dal Zotto (dz@debian.org)\n",
               I8K_VERSION);
index 61ef013b84457887fdf803c0e70fe75b713ff6fb..3601017f58cfdd936b490fc69936ab2973a864f5 100644 (file)
@@ -53,7 +53,7 @@ static int ii2Safe;         // Safe I/O address for delay routine
 
 static int iiDelayed;  // Set when the iiResetDelay function is
                                                        // called. Cleared when ANY board is reset.
-static rwlock_t Dl_spinlock;
+static DEFINE_RWLOCK(Dl_spinlock);
 
 //********
 //* Code *
@@ -82,7 +82,6 @@ static rwlock_t Dl_spinlock;
 static void
 iiEllisInit(void)
 {
-       LOCK_INIT(&Dl_spinlock);
 }
 
 //******************************************************************************
@@ -132,7 +131,7 @@ iiSetAddress( i2eBordStrPtr pB, int address, delayFunc_t delay )
                || (address & 0x7)
                )
        {
-               COMPLETE(pB,I2EE_BADADDR);
+               I2_COMPLETE(pB, I2EE_BADADDR);
        }
 
        // Initialize accelerators
@@ -152,7 +151,7 @@ iiSetAddress( i2eBordStrPtr pB, int address, delayFunc_t delay )
        pB->i2eValid = I2E_MAGIC;
        pB->i2eState = II_STATE_COLD;
 
-       COMPLETE(pB, I2EE_GOOD);
+       I2_COMPLETE(pB, I2EE_GOOD);
 }
 
 //******************************************************************************
@@ -177,12 +176,12 @@ iiReset(i2eBordStrPtr pB)
        // Magic number should be set, else even the address is suspect
        if (pB->i2eValid != I2E_MAGIC)
        {
-               COMPLETE(pB, I2EE_BADMAGIC);
+               I2_COMPLETE(pB, I2EE_BADMAGIC);
        }
 
-       OUTB(pB->i2eBase + FIFO_RESET, 0);  // Any data will do
+       outb(0, pB->i2eBase + FIFO_RESET);  /* Any data will do */
        iiDelay(pB, 50);                    // Pause between resets
-       OUTB(pB->i2eBase + FIFO_RESET, 0);  // Second reset
+       outb(0, pB->i2eBase + FIFO_RESET);  /* Second reset */
 
        // We must wait before even attempting to read anything from the FIFO: the
        // board's P.O.S.T may actually attempt to read and write its end of the
@@ -203,7 +202,7 @@ iiReset(i2eBordStrPtr pB)
        // Ensure anything which would have been of use to standard loadware is
        // blanked out, since board has now forgotten everything!.
 
-       pB->i2eUsingIrq = IRQ_UNDEFINED; // Not set up to use an interrupt yet
+       pB->i2eUsingIrq = I2_IRQ_UNDEFINED; /* to not use an interrupt so far */
        pB->i2eWaitingForEmptyFifo = 0;
        pB->i2eOutMailWaiting = 0;
        pB->i2eChannelPtr = NULL;
@@ -215,7 +214,7 @@ iiReset(i2eBordStrPtr pB)
        pB->i2eFatalTrap = NULL;
        pB->i2eFatal = 0;
 
-       COMPLETE(pB, I2EE_GOOD);
+       I2_COMPLETE(pB, I2EE_GOOD);
 }
 
 //******************************************************************************
@@ -235,14 +234,14 @@ static int
 iiResetDelay(i2eBordStrPtr pB)
 {
        if (pB->i2eValid != I2E_MAGIC) {
-               COMPLETE(pB, I2EE_BADMAGIC);
+               I2_COMPLETE(pB, I2EE_BADMAGIC);
        }
        if (pB->i2eState != II_STATE_RESET) {
-               COMPLETE(pB, I2EE_BADSTATE);
+               I2_COMPLETE(pB, I2EE_BADSTATE);
        }
        iiDelay(pB,2000);       /* Now we wait for two seconds. */
        iiDelayed = 1;          /* Delay has been called: ok to initialize */
-       COMPLETE(pB, I2EE_GOOD);
+       I2_COMPLETE(pB, I2EE_GOOD);
 }
 
 //******************************************************************************
@@ -273,12 +272,12 @@ iiInitialize(i2eBordStrPtr pB)
 
        if (pB->i2eValid != I2E_MAGIC)
        {
-               COMPLETE(pB, I2EE_BADMAGIC);
+               I2_COMPLETE(pB, I2EE_BADMAGIC);
        }
 
        if (pB->i2eState != II_STATE_RESET || !iiDelayed)
        {
-               COMPLETE(pB, I2EE_BADSTATE);
+               I2_COMPLETE(pB, I2EE_BADSTATE);
        }
 
        // In case there is a failure short of our completely reading the power-up
@@ -291,13 +290,12 @@ iiInitialize(i2eBordStrPtr pB)
        for (itemp = 0; itemp < sizeof(porStr); itemp++)
        {
                // We expect the entire message is ready.
-               if (HAS_NO_INPUT(pB))
-               {
+               if (!I2_HAS_INPUT(pB)) {
                        pB->i2ePomSize = itemp;
-                       COMPLETE(pB, I2EE_PORM_SHORT);
+                       I2_COMPLETE(pB, I2EE_PORM_SHORT);
                }
 
-               pB->i2ePom.c[itemp] = c = BYTE_FROM(pB);
+               pB->i2ePom.c[itemp] = c = inb(pB->i2eData);
 
                // We check the magic numbers as soon as they are supposed to be read
                // (rather than after) to minimize effect of reading something we
@@ -306,22 +304,22 @@ iiInitialize(i2eBordStrPtr pB)
                                (itemp == POR_2_INDEX && c != POR_MAGIC_2))
                {
                        pB->i2ePomSize = itemp+1;
-                       COMPLETE(pB, I2EE_BADMAGIC);
+                       I2_COMPLETE(pB, I2EE_BADMAGIC);
                }
        }
 
        pB->i2ePomSize = itemp;
 
        // Ensure that this was all the data...
-       if (HAS_INPUT(pB))
-               COMPLETE(pB, I2EE_PORM_LONG);
+       if (I2_HAS_INPUT(pB))
+               I2_COMPLETE(pB, I2EE_PORM_LONG);
 
        // For now, we'll fail to initialize if P.O.S.T reports bad chip mapper:
        // Implying we will not be able to download any code either:  That's ok: the
        // condition is pretty explicit.
        if (pB->i2ePom.e.porDiag1 & POR_BAD_MAPPER)
        {
-               COMPLETE(pB, I2EE_POSTERR);
+               I2_COMPLETE(pB, I2EE_POSTERR);
        }
 
        // Determine anything which must be done differently depending on the family
@@ -332,7 +330,7 @@ iiInitialize(i2eBordStrPtr pB)
 
                pB->i2eFifoStyle   = FIFO_II;
                pB->i2eFifoSize    = 512;     // 512 bytes, always
-               pB->i2eDataWidth16 = NO;
+               pB->i2eDataWidth16 = false;
 
                pB->i2eMaxIrq = 15;     // Because board cannot tell us it is in an 8-bit
                                                        // slot, we do allow it to be done (documentation!)
@@ -354,7 +352,7 @@ iiInitialize(i2eBordStrPtr pB)
                        // should always be consistent for IntelliPort-II.  Ditto below...
                        if (pB->i2ePom.e.porPorts1 != 4)
                        {
-                               COMPLETE(pB, I2EE_INCONSIST);
+                               I2_COMPLETE(pB, I2EE_INCONSIST);
                        }
                        break;
 
@@ -364,7 +362,7 @@ iiInitialize(i2eBordStrPtr pB)
                        pB->i2eChannelMap[0] = 0xff;  // Eight port
                        if (pB->i2ePom.e.porPorts1 != 8)
                        {
-                               COMPLETE(pB, I2EE_INCONSIST);
+                               I2_COMPLETE(pB, I2EE_INCONSIST);
                        }
                        break;
 
@@ -373,7 +371,7 @@ iiInitialize(i2eBordStrPtr pB)
                        pB->i2eChannelMap[0] = 0x3f;  // Six Port
                        if (pB->i2ePom.e.porPorts1 != 6)
                        {
-                               COMPLETE(pB, I2EE_INCONSIST);
+                               I2_COMPLETE(pB, I2EE_INCONSIST);
                        }
                        break;
                }
@@ -402,7 +400,7 @@ iiInitialize(i2eBordStrPtr pB)
 
                if (itemp < 8 || itemp > 15)
                {
-                       COMPLETE(pB, I2EE_INCONSIST);
+                       I2_COMPLETE(pB, I2EE_INCONSIST);
                }
                pB->i2eFifoSize = (1 << itemp);
 
@@ -450,26 +448,26 @@ iiInitialize(i2eBordStrPtr pB)
                switch (pB->i2ePom.e.porBus & (POR_BUS_SLOT16 | POR_BUS_DIP16) )
                {
                case POR_BUS_SLOT16 | POR_BUS_DIP16:
-                       pB->i2eDataWidth16 = YES;
+                       pB->i2eDataWidth16 = true;
                        pB->i2eMaxIrq = 15;
                        break;
 
                case POR_BUS_SLOT16:
-                       pB->i2eDataWidth16 = NO;
+                       pB->i2eDataWidth16 = false;
                        pB->i2eMaxIrq = 15;
                        break;
 
                case 0:
                case POR_BUS_DIP16:     // In an 8-bit slot, DIP switch don't care.
                default:
-                       pB->i2eDataWidth16 = NO;
+                       pB->i2eDataWidth16 = false;
                        pB->i2eMaxIrq = 7;
                        break;
                }
                break;   // POR_ID_FIIEX case
 
        default:    // Unknown type of board
-               COMPLETE(pB, I2EE_BAD_FAMILY);
+               I2_COMPLETE(pB, I2EE_BAD_FAMILY);
                break;
        }  // End the switch based on family
 
@@ -483,17 +481,14 @@ iiInitialize(i2eBordStrPtr pB)
        {
        case POR_BUS_T_ISA:
        case POR_BUS_T_UNK:  // If the type of bus is undeclared, assume ok.
-               pB->i2eChangeIrq = YES;
-               break;
        case POR_BUS_T_MCA:
        case POR_BUS_T_EISA:
-               pB->i2eChangeIrq = NO;
                break;
        default:
-               COMPLETE(pB, I2EE_BADBUS);
+               I2_COMPLETE(pB, I2EE_BADBUS);
        }
 
-       if (pB->i2eDataWidth16 == YES)
+       if (pB->i2eDataWidth16)
        {
                pB->i2eWriteBuf  = iiWriteBuf16;
                pB->i2eReadBuf   = iiReadBuf16;
@@ -529,7 +524,7 @@ iiInitialize(i2eBordStrPtr pB)
                break;
 
        default:
-               COMPLETE(pB, I2EE_INCONSIST);
+               I2_COMPLETE(pB, I2EE_INCONSIST);
        }
 
        // Initialize state information.
@@ -549,7 +544,7 @@ iiInitialize(i2eBordStrPtr pB)
        // Everything is ok now, return with good status/
 
        pB->i2eValid = I2E_MAGIC;
-       COMPLETE(pB, I2EE_GOOD);
+       I2_COMPLETE(pB, I2EE_GOOD);
 }
 
 //******************************************************************************
@@ -658,7 +653,7 @@ ii2DelayIO(unsigned int mseconds)
        while(mseconds--) {
                int i = ii2DelValue;
                while ( i-- ) {
-                       INB ( ii2Safe );
+                       inb(ii2Safe);
                }
        }
 }
@@ -709,11 +704,11 @@ iiWriteBuf16(i2eBordStrPtr pB, unsigned char *address, int count)
 {
        // Rudimentary sanity checking here.
        if (pB->i2eValid != I2E_MAGIC)
-               COMPLETE(pB, I2EE_INVALID);
+               I2_COMPLETE(pB, I2EE_INVALID);
 
-       OUTSW ( pB->i2eData, address, count);
+       I2_OUTSW(pB->i2eData, address, count);
 
-       COMPLETE(pB, I2EE_GOOD);
+       I2_COMPLETE(pB, I2EE_GOOD);
 }
 
 //******************************************************************************
@@ -738,11 +733,11 @@ iiWriteBuf8(i2eBordStrPtr pB, unsigned char *address, int count)
 {
        /* Rudimentary sanity checking here */
        if (pB->i2eValid != I2E_MAGIC)
-               COMPLETE(pB, I2EE_INVALID);
+               I2_COMPLETE(pB, I2EE_INVALID);
 
-       OUTSB ( pB->i2eData, address, count );
+       I2_OUTSB(pB->i2eData, address, count);
 
-       COMPLETE(pB, I2EE_GOOD);
+       I2_COMPLETE(pB, I2EE_GOOD);
 }
 
 //******************************************************************************
@@ -767,11 +762,11 @@ iiReadBuf16(i2eBordStrPtr pB, unsigned char *address, int count)
 {
        // Rudimentary sanity checking here.
        if (pB->i2eValid != I2E_MAGIC)
-               COMPLETE(pB, I2EE_INVALID);
+               I2_COMPLETE(pB, I2EE_INVALID);
 
-       INSW ( pB->i2eData, address, count);
+       I2_INSW(pB->i2eData, address, count);
 
-       COMPLETE(pB, I2EE_GOOD);
+       I2_COMPLETE(pB, I2EE_GOOD);
 }
 
 //******************************************************************************
@@ -796,11 +791,11 @@ iiReadBuf8(i2eBordStrPtr pB, unsigned char *address, int count)
 {
        // Rudimentary sanity checking here.
        if (pB->i2eValid != I2E_MAGIC)
-               COMPLETE(pB, I2EE_INVALID);
+               I2_COMPLETE(pB, I2EE_INVALID);
 
-       INSB ( pB->i2eData, address, count);
+       I2_INSB(pB->i2eData, address, count);
 
-       COMPLETE(pB, I2EE_GOOD);
+       I2_COMPLETE(pB, I2EE_GOOD);
 }
 
 //******************************************************************************
@@ -820,7 +815,7 @@ iiReadBuf8(i2eBordStrPtr pB, unsigned char *address, int count)
 static unsigned short
 iiReadWord16(i2eBordStrPtr pB)
 {
-       return (unsigned short)( INW(pB->i2eData) );
+       return inw(pB->i2eData);
 }
 
 //******************************************************************************
@@ -842,9 +837,9 @@ iiReadWord8(i2eBordStrPtr pB)
 {
        unsigned short urs;
 
-       urs = INB ( pB->i2eData );
+       urs = inb(pB->i2eData);
 
-       return ( ( INB ( pB->i2eData ) << 8 ) | urs );
+       return (inb(pB->i2eData) << 8) | urs;
 }
 
 //******************************************************************************
@@ -865,7 +860,7 @@ iiReadWord8(i2eBordStrPtr pB)
 static void
 iiWriteWord16(i2eBordStrPtr pB, unsigned short value)
 {
-       WORD_TO(pB, (int)value);
+       outw((int)value, pB->i2eData);
 }
 
 //******************************************************************************
@@ -886,8 +881,8 @@ iiWriteWord16(i2eBordStrPtr pB, unsigned short value)
 static void
 iiWriteWord8(i2eBordStrPtr pB, unsigned short value)
 {
-       BYTE_TO(pB, (char)value);
-       BYTE_TO(pB, (char)(value >> 8) );
+       outb((char)value, pB->i2eData);
+       outb((char)(value >> 8), pB->i2eData);
 }
 
 //******************************************************************************
@@ -939,30 +934,30 @@ iiWaitForTxEmptyII(i2eBordStrPtr pB, int mSdelay)
                // interrupts of any kind.
 
 
-               WRITE_LOCK_IRQSAVE(&Dl_spinlock,flags)
-               OUTB(pB->i2ePointer, SEL_COMMAND);
-               OUTB(pB->i2ePointer, SEL_CMD_SH);
+               write_lock_irqsave(&Dl_spinlock, flags);
+               outb(SEL_COMMAND, pB->i2ePointer);
+               outb(SEL_CMD_SH, pB->i2ePointer);
 
-               itemp = INB(pB->i2eStatus);
+               itemp = inb(pB->i2eStatus);
 
-               OUTB(pB->i2ePointer, SEL_COMMAND);
-               OUTB(pB->i2ePointer, SEL_CMD_UNSH);
+               outb(SEL_COMMAND, pB->i2ePointer);
+               outb(SEL_CMD_UNSH, pB->i2ePointer);
 
                if (itemp & ST_IN_EMPTY)
                {
-                       UPDATE_FIFO_ROOM(pB);
-                       WRITE_UNLOCK_IRQRESTORE(&Dl_spinlock,flags)
-                       COMPLETE(pB, I2EE_GOOD);
+                       I2_UPDATE_FIFO_ROOM(pB);
+                       write_unlock_irqrestore(&Dl_spinlock, flags);
+                       I2_COMPLETE(pB, I2EE_GOOD);
                }
 
-               WRITE_UNLOCK_IRQRESTORE(&Dl_spinlock,flags)
+               write_unlock_irqrestore(&Dl_spinlock, flags);
 
                if (mSdelay-- == 0)
                        break;
 
                iiDelay(pB, 1);      /* 1 mS granularity on checking condition */
        }
-       COMPLETE(pB, I2EE_TXE_TIME);
+       I2_COMPLETE(pB, I2EE_TXE_TIME);
 }
 
 //******************************************************************************
@@ -1002,21 +997,21 @@ iiWaitForTxEmptyIIEX(i2eBordStrPtr pB, int mSdelay)
                // you will generally not want to service interrupts or in any way
                // disrupt the assumptions implicit in the larger context.
 
-               WRITE_LOCK_IRQSAVE(&Dl_spinlock,flags)
+               write_lock_irqsave(&Dl_spinlock, flags);
 
-               if (INB(pB->i2eStatus) & STE_OUT_MT) {
-                       UPDATE_FIFO_ROOM(pB);
-                       WRITE_UNLOCK_IRQRESTORE(&Dl_spinlock,flags)
-                       COMPLETE(pB, I2EE_GOOD);
+               if (inb(pB->i2eStatus) & STE_OUT_MT) {
+                       I2_UPDATE_FIFO_ROOM(pB);
+                       write_unlock_irqrestore(&Dl_spinlock, flags);
+                       I2_COMPLETE(pB, I2EE_GOOD);
                }
-               WRITE_UNLOCK_IRQRESTORE(&Dl_spinlock,flags)
+               write_unlock_irqrestore(&Dl_spinlock, flags);
 
                if (mSdelay-- == 0)
                        break;
 
                iiDelay(pB, 1);      // 1 mS granularity on checking condition
        }
-       COMPLETE(pB, I2EE_TXE_TIME);
+       I2_COMPLETE(pB, I2EE_TXE_TIME);
 }
 
 //******************************************************************************
@@ -1038,8 +1033,8 @@ static int
 iiTxMailEmptyII(i2eBordStrPtr pB)
 {
        int port = pB->i2ePointer;
-       OUTB ( port, SEL_OUTMAIL );
-       return ( INB(port) == 0 );
+       outb(SEL_OUTMAIL, port);
+       return inb(port) == 0;
 }
 
 //******************************************************************************
@@ -1060,7 +1055,7 @@ iiTxMailEmptyII(i2eBordStrPtr pB)
 static int
 iiTxMailEmptyIIEX(i2eBordStrPtr pB)
 {
-       return !(INB(pB->i2eStatus) & STE_OUT_MAIL);
+       return !(inb(pB->i2eStatus) & STE_OUT_MAIL);
 }
 
 //******************************************************************************
@@ -1084,10 +1079,10 @@ iiTrySendMailII(i2eBordStrPtr pB, unsigned char mail)
 {
        int port = pB->i2ePointer;
 
-       OUTB(port, SEL_OUTMAIL);
-       if (INB(port) == 0) {
-               OUTB(port, SEL_OUTMAIL);
-               OUTB(port, mail);
+       outb(SEL_OUTMAIL, port);
+       if (inb(port) == 0) {
+               outb(SEL_OUTMAIL, port);
+               outb(mail, port);
                return 1;
        }
        return 0;
@@ -1112,10 +1107,9 @@ iiTrySendMailII(i2eBordStrPtr pB, unsigned char mail)
 static int
 iiTrySendMailIIEX(i2eBordStrPtr pB, unsigned char mail)
 {
-       if(INB(pB->i2eStatus) & STE_OUT_MAIL) {
+       if (inb(pB->i2eStatus) & STE_OUT_MAIL)
                return 0;
-       }
-       OUTB(pB->i2eXMail, mail);
+       outb(mail, pB->i2eXMail);
        return 1;
 }
 
@@ -1136,9 +1130,9 @@ iiTrySendMailIIEX(i2eBordStrPtr pB, unsigned char mail)
 static unsigned short
 iiGetMailII(i2eBordStrPtr pB)
 {
-       if (HAS_MAIL(pB)) {
-               OUTB(pB->i2ePointer, SEL_INMAIL);
-               return INB(pB->i2ePointer);
+       if (I2_HAS_MAIL(pB)) {
+               outb(SEL_INMAIL, pB->i2ePointer);
+               return inb(pB->i2ePointer);
        } else {
                return NO_MAIL_HERE;
        }
@@ -1161,11 +1155,10 @@ iiGetMailII(i2eBordStrPtr pB)
 static unsigned short
 iiGetMailIIEX(i2eBordStrPtr pB)
 {
-       if (HAS_MAIL(pB)) {
-               return INB(pB->i2eXMail);
-       } else {
+       if (I2_HAS_MAIL(pB))
+               return inb(pB->i2eXMail);
+       else
                return NO_MAIL_HERE;
-       }
 }
 
 //******************************************************************************
@@ -1184,8 +1177,8 @@ iiGetMailIIEX(i2eBordStrPtr pB)
 static void
 iiEnableMailIrqII(i2eBordStrPtr pB)
 {
-       OUTB(pB->i2ePointer, SEL_MASK);
-       OUTB(pB->i2ePointer, ST_IN_MAIL);
+       outb(SEL_MASK, pB->i2ePointer);
+       outb(ST_IN_MAIL, pB->i2ePointer);
 }
 
 //******************************************************************************
@@ -1204,7 +1197,7 @@ iiEnableMailIrqII(i2eBordStrPtr pB)
 static void
 iiEnableMailIrqIIEX(i2eBordStrPtr pB)
 {
-       OUTB(pB->i2eXMask, MX_IN_MAIL);
+       outb(MX_IN_MAIL, pB->i2eXMask);
 }
 
 //******************************************************************************
@@ -1223,8 +1216,8 @@ iiEnableMailIrqIIEX(i2eBordStrPtr pB)
 static void
 iiWriteMaskII(i2eBordStrPtr pB, unsigned char value)
 {
-       OUTB(pB->i2ePointer, SEL_MASK);
-       OUTB(pB->i2ePointer, value);
+       outb(SEL_MASK, pB->i2ePointer);
+       outb(value, pB->i2ePointer);
 }
 
 //******************************************************************************
@@ -1243,7 +1236,7 @@ iiWriteMaskII(i2eBordStrPtr pB, unsigned char value)
 static void
 iiWriteMaskIIEX(i2eBordStrPtr pB, unsigned char value)
 {
-       OUTB(pB->i2eXMask, value);
+       outb(value, pB->i2eXMask);
 }
 
 //******************************************************************************
@@ -1354,9 +1347,8 @@ iiDownloadBlock ( i2eBordStrPtr pB, loadHdrStrPtr pSource, int isStandard)
        // immediately and be harmless, though not strictly necessary.
        itemp = MAX_DLOAD_ACK_TIME/10;
        while (--itemp) {
-               if (HAS_INPUT(pB)) {
-                       switch(BYTE_FROM(pB))
-                       {
+               if (I2_HAS_INPUT(pB)) {
+                       switch (inb(pB->i2eData)) {
                        case LOADWARE_OK:
                                pB->i2eState =
                                        isStandard ? II_STATE_STDLOADED :II_STATE_LOADED;
index 433305062fb8aa4f7c070d4c8ae7e968d766be1b..c88a64e527aa510012e249f1037ae853186b0dbc 100644 (file)
@@ -185,10 +185,6 @@ typedef struct _i2eBordStr
                                                // The highest allowable IRQ, based on the
                                                // slot size.
 
-       unsigned char  i2eChangeIrq;
-                                               // Whether tis valid to change IRQ's
-                                               // ISA = ok, EISA, MicroChannel, no
-
        // Accelerators for various addresses on the board
        int            i2eBase;        // I/O Address of the Board
        int            i2eData;        // From here data transfers happen
@@ -431,12 +427,6 @@ typedef struct _i2eBordStr
 // Manifests for i2eBordStr:
 //-------------------------------------------
 
-#define YES 1
-#define NO  0
-
-#define NULLFUNC (void (*)(void))0
-#define NULLPTR (void *)0
-
 typedef void (*delayFunc_t)(unsigned int);
 
 // i2eValid
@@ -494,8 +484,8 @@ typedef void (*delayFunc_t)(unsigned int);
 
 // i2eUsingIrq
 //
-#define IRQ_UNDEFINED   0x1352  // No valid irq (or polling = 0) can ever
-                                                               // promote to this!
+#define I2_IRQ_UNDEFINED       0x1352  /* No valid irq (or polling = 0) can
+                                        * ever promote to this! */
 //------------------------------------------
 // Handy Macros for i2ellis.c and others
 // Note these are common to -II and -IIEX
@@ -504,41 +494,14 @@ typedef void (*delayFunc_t)(unsigned int);
 // Given a pointer to the board structure, does the input FIFO have any data or
 // not?
 //
-#define HAS_INPUT(pB)      !(INB(pB->i2eStatus) & ST_IN_EMPTY)
-#define HAS_NO_INPUT(pB)   (INB(pB->i2eStatus) & ST_IN_EMPTY)
-
-// Given a pointer to board structure, read a byte or word from the fifo
-//
-#define BYTE_FROM(pB)      (unsigned char)INB(pB->i2eData)
-#define WORD_FROM(pB)      (unsigned short)INW(pB->i2eData)
-
-// Given a pointer to board structure, is there room for any data to be written
-// to the data fifo?
-//
-#define HAS_OUTROOM(pB)    !(INB(pB->i2eStatus) & ST_OUT_FULL)
-#define HAS_NO_OUTROOM(pB) (INB(pB->i2eStatus) & ST_OUT_FULL)
-
-// Given a pointer to board structure, write a single byte to the fifo
-// structure. Note that for 16-bit interfaces, the high order byte is undefined
-// and unknown.
-//
-#define BYTE_TO(pB, c)     OUTB(pB->i2eData,(c))
-
-// Write a word to the fifo structure. For 8-bit interfaces, this may have
-// unknown results.
-//
-#define WORD_TO(pB, c)     OUTW(pB->i2eData,(c))
+#define I2_HAS_INPUT(pB)       !(inb(pB->i2eStatus) & ST_IN_EMPTY)
 
 // Given a pointer to the board structure, is there anything in the incoming
 // mailbox?
 //
-#define HAS_MAIL(pB)       (INB(pB->i2eStatus) & ST_IN_MAIL)
+#define I2_HAS_MAIL(pB)                (inb(pB->i2eStatus) & ST_IN_MAIL)
 
-#define UPDATE_FIFO_ROOM(pB)  (pB)->i2eFifoRemains=(pB)->i2eFifoSize
-
-// Handy macro to round up a number (like the buffer write and read routines do)
-// 
-#define ROUNDUP(number)    (((number)+1) & (~1))
+#define I2_UPDATE_FIFO_ROOM(pB)        ((pB)->i2eFifoRemains = (pB)->i2eFifoSize)
 
 //------------------------------------------
 // Function Declarations for i2ellis.c
@@ -593,20 +556,11 @@ static int iiDownloadBlock(i2eBordStrPtr, loadHdrStrPtr, int);
 //
 static int iiDownloadAll(i2eBordStrPtr, loadHdrStrPtr, int, int);
 
-// Called indirectly always.  Needed externally so the routine might be
-// SPECIFIED as an argument to iiReset()
-//
-//static void ii2DelayIO(unsigned int);                // N-millisecond delay using
-                                                                                       //hardware spin
-//static void ii2DelayTimer(unsigned int);     // N-millisecond delay using Linux
-                                                                                       //timer
-
 // Many functions defined here return True if good, False otherwise, with an
 // error code in i2eError field. Here is a handy macro for setting the error
 // code and returning.
 //
-#define COMPLETE(pB,code) \
-       do { \
+#define I2_COMPLETE(pB,code) do { \
                 pB->i2eError = code; \
                 return (code == I2EE_GOOD);\
        } while (0)
index 15fe04e748f4bf2d1954a04a900abc596837f288..8aa6e7ab8d5b503b1d4a5f36290b622bf79e39cc 100644 (file)
@@ -129,7 +129,6 @@ registers, use byte operations only.
 //------------------------------------------------
 //
 #include "ip2types.h"
-#include "i2os.h"    /* For any o.s., compiler, or host-related issues */
 
 //-------------------------------------------------------------------------
 // Manifests for the I/O map:
@@ -644,5 +643,10 @@ typedef union _loadHdrStr
 #define ABS_BIGGEST_BOX 16    // Absolute the most ports per box
 #define ABS_MOST_PORTS  (ABS_MAX_BOXES * ABS_BIGGEST_BOX)
 
+#define I2_OUTSW(port, addr, count)    outsw((port), (addr), (((count)+1)/2))
+#define I2_OUTSB(port, addr, count)    outsb((port), (addr), (((count)+1))&-2)
+#define I2_INSW(port, addr, count)     insw((port), (addr), (((count)+1)/2))
+#define I2_INSB(port, addr, count)     insb((port), (addr), (((count)+1))&-2)
+
 #endif   // I2HW_H
 
index 9c25320121efe88f911901ec38a95e76b66c2a9e..938879cc7bccc66e394a32c034a45fcb0c79be27 100644 (file)
@@ -227,17 +227,17 @@ i2InitChannels ( i2eBordStrPtr pB, int nChannels, i2ChanStrPtr pCh)
        i2ChanStrPtr *ppCh;
        
        if (pB->i2eValid != I2E_MAGIC) {
-               COMPLETE(pB, I2EE_BADMAGIC);
+               I2_COMPLETE(pB, I2EE_BADMAGIC);
        }
        if (pB->i2eState != II_STATE_STDLOADED) {
-               COMPLETE(pB, I2EE_BADSTATE);
+               I2_COMPLETE(pB, I2EE_BADSTATE);
        }
 
-       LOCK_INIT(&pB->read_fifo_spinlock);
-       LOCK_INIT(&pB->write_fifo_spinlock);
-       LOCK_INIT(&pB->Dbuf_spinlock);
-       LOCK_INIT(&pB->Bbuf_spinlock);
-       LOCK_INIT(&pB->Fbuf_spinlock);
+       rwlock_init(&pB->read_fifo_spinlock);
+       rwlock_init(&pB->write_fifo_spinlock);
+       rwlock_init(&pB->Dbuf_spinlock);
+       rwlock_init(&pB->Bbuf_spinlock);
+       rwlock_init(&pB->Fbuf_spinlock);
        
        // NO LOCK needed yet - this is init
 
@@ -259,10 +259,10 @@ i2InitChannels ( i2eBordStrPtr pB, int nChannels, i2ChanStrPtr pCh)
                if ( !(pB->i2eChannelMap[index >> 4] & (1 << (index & 0xf)) ) ) {
                        continue;
                }
-               LOCK_INIT(&pCh->Ibuf_spinlock);
-               LOCK_INIT(&pCh->Obuf_spinlock);
-               LOCK_INIT(&pCh->Cbuf_spinlock);
-               LOCK_INIT(&pCh->Pbuf_spinlock);
+               rwlock_init(&pCh->Ibuf_spinlock);
+               rwlock_init(&pCh->Obuf_spinlock);
+               rwlock_init(&pCh->Cbuf_spinlock);
+               rwlock_init(&pCh->Pbuf_spinlock);
                // NO LOCK needed yet - this is init
                // Set up validity flag according to support level
                if (pB->i2eGoodMap[index >> 4] & (1 << (index & 0xf)) ) {
@@ -347,7 +347,7 @@ i2InitChannels ( i2eBordStrPtr pB, int nChannels, i2ChanStrPtr pCh)
        }
        // No need to check for wrap here; this is initialization.
        pB->i2Fbuf_stuff = stuffIndex;
-       COMPLETE(pB, I2EE_GOOD);
+       I2_COMPLETE(pB, I2EE_GOOD);
 
 }
 
@@ -374,7 +374,7 @@ i2DeQueueNeeds(i2eBordStrPtr pB, int type)
 
        case  NEED_INLINE:
 
-               WRITE_LOCK_IRQSAVE(&pB->Dbuf_spinlock,flags);
+               write_lock_irqsave(&pB->Dbuf_spinlock, flags);
                if ( pB->i2Dbuf_stuff != pB->i2Dbuf_strip)
                {
                        queueIndex = pB->i2Dbuf_strip;
@@ -386,12 +386,12 @@ i2DeQueueNeeds(i2eBordStrPtr pB, int type)
                        pB->i2Dbuf_strip = queueIndex;
                        pCh->channelNeeds &= ~NEED_INLINE;
                }
-               WRITE_UNLOCK_IRQRESTORE(&pB->Dbuf_spinlock,flags); 
+               write_unlock_irqrestore(&pB->Dbuf_spinlock, flags);
                break;
 
        case NEED_BYPASS:
 
-               WRITE_LOCK_IRQSAVE(&pB->Bbuf_spinlock,flags);
+               write_lock_irqsave(&pB->Bbuf_spinlock, flags);
                if (pB->i2Bbuf_stuff != pB->i2Bbuf_strip)
                {
                        queueIndex = pB->i2Bbuf_strip;
@@ -403,12 +403,12 @@ i2DeQueueNeeds(i2eBordStrPtr pB, int type)
                        pB->i2Bbuf_strip = queueIndex;
                        pCh->channelNeeds &= ~NEED_BYPASS;
                }
-               WRITE_UNLOCK_IRQRESTORE(&pB->Bbuf_spinlock,flags); 
+               write_unlock_irqrestore(&pB->Bbuf_spinlock, flags);
                break;
        
        case NEED_FLOW:
 
-               WRITE_LOCK_IRQSAVE(&pB->Fbuf_spinlock,flags);
+               write_lock_irqsave(&pB->Fbuf_spinlock, flags);
                if (pB->i2Fbuf_stuff != pB->i2Fbuf_strip)
                {
                        queueIndex = pB->i2Fbuf_strip;
@@ -420,7 +420,7 @@ i2DeQueueNeeds(i2eBordStrPtr pB, int type)
                        pB->i2Fbuf_strip = queueIndex;
                        pCh->channelNeeds &= ~NEED_FLOW;
                }
-               WRITE_UNLOCK_IRQRESTORE(&pB->Fbuf_spinlock,flags); 
+               write_unlock_irqrestore(&pB->Fbuf_spinlock, flags);
                break;
        default:
                printk(KERN_ERR "i2DeQueueNeeds called with bad type:%x\n",type);
@@ -453,7 +453,7 @@ i2QueueNeeds(i2eBordStrPtr pB, i2ChanStrPtr pCh, int type)
 
        case NEED_INLINE:
 
-               WRITE_LOCK_IRQSAVE(&pB->Dbuf_spinlock,flags);
+               write_lock_irqsave(&pB->Dbuf_spinlock, flags);
                if ( !(pCh->channelNeeds & NEED_INLINE) )
                {
                        pCh->channelNeeds |= NEED_INLINE;
@@ -463,12 +463,12 @@ i2QueueNeeds(i2eBordStrPtr pB, i2ChanStrPtr pCh, int type)
                                queueIndex = 0;
                        pB->i2Dbuf_stuff = queueIndex;
                }
-               WRITE_UNLOCK_IRQRESTORE(&pB->Dbuf_spinlock,flags); 
+               write_unlock_irqrestore(&pB->Dbuf_spinlock, flags);
                break;
 
        case NEED_BYPASS:
 
-               WRITE_LOCK_IRQSAVE(&pB->Bbuf_spinlock,flags);
+               write_lock_irqsave(&pB->Bbuf_spinlock, flags);
                if ((type & NEED_BYPASS) && !(pCh->channelNeeds & NEED_BYPASS))
                {
                        pCh->channelNeeds |= NEED_BYPASS;
@@ -478,12 +478,12 @@ i2QueueNeeds(i2eBordStrPtr pB, i2ChanStrPtr pCh, int type)
                                queueIndex = 0;
                        pB->i2Bbuf_stuff = queueIndex;
                } 
-               WRITE_UNLOCK_IRQRESTORE(&pB->Bbuf_spinlock,flags); 
+               write_unlock_irqrestore(&pB->Bbuf_spinlock, flags);
                break;
 
        case NEED_FLOW:
 
-               WRITE_LOCK_IRQSAVE(&pB->Fbuf_spinlock,flags);
+               write_lock_irqsave(&pB->Fbuf_spinlock, flags);
                if ((type & NEED_FLOW) && !(pCh->channelNeeds & NEED_FLOW))
                {
                        pCh->channelNeeds |= NEED_FLOW;
@@ -493,7 +493,7 @@ i2QueueNeeds(i2eBordStrPtr pB, i2ChanStrPtr pCh, int type)
                                queueIndex = 0;
                        pB->i2Fbuf_stuff = queueIndex;
                }
-               WRITE_UNLOCK_IRQRESTORE(&pB->Fbuf_spinlock,flags); 
+               write_unlock_irqrestore(&pB->Fbuf_spinlock, flags);
                break;
 
        case NEED_CREDIT:
@@ -562,9 +562,8 @@ i2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands,
        pB = pCh->pMyBord;
 
        // Board must also exist, and THE INTERRUPT COMMAND ALREADY SENT
-       if (pB->i2eValid != I2E_MAGIC || pB->i2eUsingIrq == IRQ_UNDEFINED) {
+       if (pB->i2eValid != I2E_MAGIC || pB->i2eUsingIrq == I2_IRQ_UNDEFINED)
                return -2;
-       }
        // If the board has gone fatal, return bad, and also hit the trap routine if
        // it exists.
        if (pB->i2eFatal) {
@@ -620,13 +619,13 @@ i2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands,
                        switch(type) {
                        case PTYPE_INLINE:
                                lock_var_p = &pCh->Obuf_spinlock;
-                               WRITE_LOCK_IRQSAVE(lock_var_p,flags);
+                               write_lock_irqsave(lock_var_p, flags);
                                stuffIndex = pCh->Obuf_stuff;
                                bufroom = pCh->Obuf_strip - stuffIndex;
                                break;
                        case PTYPE_BYPASS:
                                lock_var_p = &pCh->Cbuf_spinlock;
-                               WRITE_LOCK_IRQSAVE(lock_var_p,flags);
+                               write_lock_irqsave(lock_var_p, flags);
                                stuffIndex = pCh->Cbuf_stuff;
                                bufroom = pCh->Cbuf_strip - stuffIndex;
                                break;
@@ -645,7 +644,7 @@ i2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands,
                                break; /* from for()- Enough room: goto proceed */
                        }
                        ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize);
-                       WRITE_UNLOCK_IRQRESTORE(lock_var_p, flags);
+                       write_unlock_irqrestore(lock_var_p, flags);
                } else
                        ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize);
 
@@ -747,7 +746,7 @@ i2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands,
        {
        case PTYPE_INLINE:
                pCh->Obuf_stuff = stuffIndex;  // Store buffer pointer
-               WRITE_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags); 
+               write_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
 
                pB->debugInlineQueued++;
                // Add the channel pointer to list of channels needing service (first
@@ -757,7 +756,7 @@ i2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands,
 
        case PTYPE_BYPASS:
                pCh->Cbuf_stuff = stuffIndex;  // Store buffer pointer
-               WRITE_UNLOCK_IRQRESTORE(&pCh->Cbuf_spinlock,flags); 
+               write_unlock_irqrestore(&pCh->Cbuf_spinlock, flags);
 
                pB->debugBypassQueued++;
                // Add the channel pointer to list of channels needing service (first
@@ -840,7 +839,7 @@ i2Input(i2ChanStrPtr pCh)
                count = -1;
                goto i2Input_exit;
        }
-       WRITE_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags);
+       write_lock_irqsave(&pCh->Ibuf_spinlock, flags);
 
        // initialize some accelerators and private copies
        stripIndex = pCh->Ibuf_strip;
@@ -850,7 +849,7 @@ i2Input(i2ChanStrPtr pCh)
        // If buffer is empty or requested data count was 0, (trivial case) return
        // without any further thought.
        if ( count == 0 ) {
-               WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags);
+               write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
                goto i2Input_exit;
        }
        // Adjust for buffer wrap
@@ -891,10 +890,10 @@ i2Input(i2ChanStrPtr pCh)
 
        if ((pCh->sinceLastFlow += count) >= pCh->whenSendFlow) {
                pCh->sinceLastFlow -= pCh->whenSendFlow;
-               WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags);
+               write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
                i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW);
        } else {
-               WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags);
+               write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
        }
 
 i2Input_exit:
@@ -926,7 +925,7 @@ i2InputFlush(i2ChanStrPtr pCh)
 
        ip2trace (CHANN, ITRC_INPUT, 10, 0);
 
-       WRITE_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags);
+       write_lock_irqsave(&pCh->Ibuf_spinlock, flags);
        count = pCh->Ibuf_stuff - pCh->Ibuf_strip;
 
        // Adjust for buffer wrap
@@ -947,10 +946,10 @@ i2InputFlush(i2ChanStrPtr pCh)
        if ( (pCh->sinceLastFlow += count) >= pCh->whenSendFlow )
        {
                pCh->sinceLastFlow -= pCh->whenSendFlow;
-               WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags);
+               write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
                i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW);
        } else {
-               WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags);
+               write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
        }
 
        ip2trace (CHANN, ITRC_INPUT, 19, 1, count);
@@ -979,9 +978,9 @@ i2InputAvailable(i2ChanStrPtr pCh)
 
 
        // initialize some accelerators and private copies
-       READ_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags);
+       read_lock_irqsave(&pCh->Ibuf_spinlock, flags);
        count = pCh->Ibuf_stuff - pCh->Ibuf_strip;
-       READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags);
+       read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
 
        // Adjust for buffer wrap
        if (count < 0)
@@ -1045,9 +1044,9 @@ i2Output(i2ChanStrPtr pCh, const char *pSource, int count)
        while ( count > 0 ) {
 
                // How much room in output buffer is there?
-               READ_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags);
+               read_lock_irqsave(&pCh->Obuf_spinlock, flags);
                amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1;
-               READ_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags);
+               read_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
                if (amountToMove < 0) {
                        amountToMove += OBUF_SIZE;
                }
@@ -1075,7 +1074,7 @@ i2Output(i2ChanStrPtr pCh, const char *pSource, int count)
                if ( !(pCh->flush_flags && i2RetryFlushOutput(pCh) ) 
                                && amountToMove > 0 )
                {
-                       WRITE_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags);
+                       write_lock_irqsave(&pCh->Obuf_spinlock, flags);
                        stuffIndex = pCh->Obuf_stuff;
       
                        // Had room to move some data: don't know whether the block size,
@@ -1102,7 +1101,7 @@ i2Output(i2ChanStrPtr pCh, const char *pSource, int count)
                        }
                        pCh->Obuf_stuff = stuffIndex;
 
-                       WRITE_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags);
+                       write_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
 
                        ip2trace (CHANN, ITRC_OUTPUT, 13, 1, stuffIndex );
 
@@ -1352,9 +1351,9 @@ i2OutputFree(i2ChanStrPtr pCh)
        if ( !i2Validate ( pCh ) ) {
                return -1;
        }
-       READ_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags);
+       read_lock_irqsave(&pCh->Obuf_spinlock, flags);
        amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1;
-       READ_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags);
+       read_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
 
        if (amountToMove < 0) {
                amountToMove += OBUF_SIZE;
@@ -1464,11 +1463,11 @@ i2StripFifo(i2eBordStrPtr pB)
 
 //     ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_ENTER, 0 );
 
-       while (HAS_INPUT(pB)) {
+       while (I2_HAS_INPUT(pB)) {
 //             ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 2, 0 );
 
                // Process packet from fifo a one atomic unit
-               WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock,bflags);
+               write_lock_irqsave(&pB->read_fifo_spinlock, bflags);
    
                // The first word (or two bytes) will have channel number and type of
                // packet, possibly other information
@@ -1490,7 +1489,8 @@ i2StripFifo(i2eBordStrPtr pB)
 // sick!
                        if ( ((unsigned int)count) > IBUF_SIZE ) {
                                pB->i2eFatal = 2;
-                               WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock,bflags);
+                               write_unlock_irqrestore(&pB->read_fifo_spinlock,
+                                               bflags);
                                return;     /* Bail out ASAP */
                        }
                        // Channel is illegally big ?
@@ -1498,7 +1498,8 @@ i2StripFifo(i2eBordStrPtr pB)
                                (NULL==(pCh = ((i2ChanStrPtr*)pB->i2eChannelPtr)[channel])))
                        {
                                iiReadBuf(pB, junkBuffer, count);
-                               WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock,bflags);
+                               write_unlock_irqrestore(&pB->read_fifo_spinlock,
+                                               bflags);
                                break;         /* From switch: ready for next packet */
                        }
 
@@ -1512,14 +1513,15 @@ i2StripFifo(i2eBordStrPtr pB)
                        if(ID_OF(pB->i2eLeadoffWord) == ID_HOT_KEY)
                        {
                                pCh->hotKeyIn = iiReadWord(pB) & 0xff;
-                               WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock,bflags);
+                               write_unlock_irqrestore(&pB->read_fifo_spinlock,
+                                               bflags);
                                i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_HOTACK);
                                break;   /* From the switch: ready for next packet */
                        }
 
                        // Normal data! We crudely assume there is room for the data in our
                        // buffer because the board wouldn't have exceeded his credit limit.
-                       WRITE_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,cflags);
+                       write_lock_irqsave(&pCh->Ibuf_spinlock, cflags);
                                                                                                        // We have 2 locks now
                        stuffIndex = pCh->Ibuf_stuff;
                        amountToRead = IBUF_SIZE - stuffIndex;
@@ -1562,8 +1564,9 @@ i2StripFifo(i2eBordStrPtr pB)
 
                        // Update stuff index
                        pCh->Ibuf_stuff = stuffIndex;
-                       WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,cflags);
-                       WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock,bflags);
+                       write_unlock_irqrestore(&pCh->Ibuf_spinlock, cflags);
+                       write_unlock_irqrestore(&pB->read_fifo_spinlock,
+                                       bflags);
 
 #ifdef USE_IQ
                        schedule_work(&pCh->tqueue_input);
@@ -1585,7 +1588,8 @@ i2StripFifo(i2eBordStrPtr pB)
 
                        iiReadBuf(pB, cmdBuffer, count);
                        // We can release early with buffer grab
-                       WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock,bflags);
+                       write_unlock_irqrestore(&pB->read_fifo_spinlock,
+                                       bflags);
 
                        pc = cmdBuffer;
                        pcLimit = &(cmdBuffer[count]);
@@ -1830,12 +1834,12 @@ i2StripFifo(i2eBordStrPtr pB)
                default: // Neither packet? should be impossible
                        ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 5, 1,
                                PTYPE_OF(pB->i2eLeadoffWord) );
-                       WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock,
+                       write_unlock_irqrestore(&pB->read_fifo_spinlock,
                                        bflags);
 
                        break;
                }  // End of switch on type of packets
-       }       //while(board HAS_INPUT)
+       }       /*while(board I2_HAS_INPUT)*/
 
        ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_RETURN, 0 );
 
@@ -1858,7 +1862,7 @@ i2Write2Fifo(i2eBordStrPtr pB, unsigned char *source, int count,int reserve)
 {
        int rc = 0;
        unsigned long flags;
-       WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags);
+       write_lock_irqsave(&pB->write_fifo_spinlock, flags);
        if (!pB->i2eWaitingForEmptyFifo) {
                if (pB->i2eFifoRemains > (count+reserve)) {
                        pB->i2eFifoRemains -= count;
@@ -1867,7 +1871,7 @@ i2Write2Fifo(i2eBordStrPtr pB, unsigned char *source, int count,int reserve)
                        rc =  count;
                }
        }
-       WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags);
+       write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
        return rc;
 }
 //******************************************************************************
@@ -1898,7 +1902,7 @@ i2StuffFifoBypass(i2eBordStrPtr pB)
        while ( --bailout && notClogged && 
                        (NULL != (pCh = i2DeQueueNeeds(pB,NEED_BYPASS))))
        {
-               WRITE_LOCK_IRQSAVE(&pCh->Cbuf_spinlock,flags);
+               write_lock_irqsave(&pCh->Cbuf_spinlock, flags);
                stripIndex = pCh->Cbuf_strip;
 
                // as long as there are packets for this channel...
@@ -1906,7 +1910,7 @@ i2StuffFifoBypass(i2eBordStrPtr pB)
                while (stripIndex != pCh->Cbuf_stuff) {
                        pRemove = &(pCh->Cbuf[stripIndex]);
                        packetSize = CMD_COUNT_OF(pRemove) + sizeof(i2CmdHeader);
-                       paddedSize = ROUNDUP(packetSize);
+                       paddedSize = roundup(packetSize, 2);
 
                        if (paddedSize > 0) {
                                if ( 0 == i2Write2Fifo(pB, pRemove, paddedSize,0)) {
@@ -1930,7 +1934,7 @@ WriteDBGBuf("BYPS", pRemove, paddedSize);
                // Done with this channel. Move to next, removing this one from 
                // the queue of channels if we cleaned it out (i.e., didn't get clogged.
                pCh->Cbuf_strip = stripIndex;
-               WRITE_UNLOCK_IRQRESTORE(&pCh->Cbuf_spinlock,flags);
+               write_unlock_irqrestore(&pCh->Cbuf_spinlock, flags);
        }  // Either clogged or finished all the work
 
 #ifdef IP2DEBUG_TRACE
@@ -1954,7 +1958,7 @@ static inline void
 i2StuffFifoFlow(i2eBordStrPtr pB)
 {
        i2ChanStrPtr pCh;
-       unsigned short paddedSize               = ROUNDUP(sizeof(flowIn));
+       unsigned short paddedSize = roundup(sizeof(flowIn), 2);
 
        ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_ENTER, 2,
                pB->i2eFifoRemains, paddedSize );
@@ -2010,7 +2014,7 @@ i2StuffFifoInline(i2eBordStrPtr pB)
        while ( --bailout && notClogged && 
                        (NULL != (pCh = i2DeQueueNeeds(pB,NEED_INLINE))) )
        {
-               WRITE_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags);
+               write_lock_irqsave(&pCh->Obuf_spinlock, flags);
                stripIndex = pCh->Obuf_strip;
 
                ip2trace (CHANN, ITRC_SICMD, 3, 2, stripIndex, pCh->Obuf_stuff );
@@ -2031,7 +2035,7 @@ i2StuffFifoInline(i2eBordStrPtr pB)
                                packetSize = flowsize + sizeof(i2CmdHeader);
                        }
                        flowsize = CREDIT_USAGE(flowsize);
-                       paddedSize = ROUNDUP(packetSize);
+                       paddedSize = roundup(packetSize, 2);
 
                        ip2trace (CHANN, ITRC_SICMD, 4, 2, pB->i2eFifoRemains, paddedSize );
 
@@ -2086,7 +2090,7 @@ WriteDBGBuf("DATA", pRemove, paddedSize);
                // Done with this channel. Move to next, removing this one from the
                // queue of channels if we cleaned it out (i.e., didn't get clogged.
                pCh->Obuf_strip = stripIndex;
-               WRITE_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags);
+               write_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
                if ( notClogged )
                {
 
@@ -2190,10 +2194,11 @@ i2ServiceBoard ( i2eBordStrPtr pB )
 
                if (inmail & MB_OUT_STRIPPED) {
                        pB->i2eFifoOutInts++;
-                       WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags);
+                       write_lock_irqsave(&pB->write_fifo_spinlock, flags);
                        pB->i2eFifoRemains = pB->i2eFifoSize;
                        pB->i2eWaitingForEmptyFifo = 0;
-                       WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags);
+                       write_unlock_irqrestore(&pB->write_fifo_spinlock,
+                                       flags);
 
                        ip2trace (ITRC_NO_PORT, ITRC_INTR, 30, 1, pB->i2eFifoRemains );
 
diff --git a/drivers/char/ip2/i2os.h b/drivers/char/ip2/i2os.h
deleted file mode 100644 (file)
index eff9b54..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1999 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Defines, definitions and includes which are heavily dependent
-*                on O/S, host, compiler, etc. This file is tailored for:
-*                 Linux v2.0.0 and later
-*                 Gnu gcc c2.7.2
-*                 80x86 architecture
-*
-*******************************************************************************/
-
-#ifndef I2OS_H    /* To prevent multiple includes */
-#define I2OS_H 1
-
-//-------------------------------------------------
-// Required Includes
-//-------------------------------------------------
-
-#include "ip2types.h"
-#include <asm/io.h>  /* For inb, etc */
-
-//------------------------------------
-// Defines for I/O instructions:
-//------------------------------------
-
-#define INB(port)                inb(port)
-#define OUTB(port,value)         outb((value),(port))
-#define INW(port)                inw(port)
-#define OUTW(port,value)         outw((value),(port))
-#define OUTSW(port,addr,count)   outsw((port),(addr),(((count)+1)/2))
-#define OUTSB(port,addr,count)   outsb((port),(addr),(((count)+1))&-2)
-#define INSW(port,addr,count)    insw((port),(addr),(((count)+1)/2))
-#define INSB(port,addr,count)    insb((port),(addr),(((count)+1))&-2)
-
-//--------------------------------------------
-// Interrupt control
-//--------------------------------------------
-
-#define LOCK_INIT(a)   rwlock_init(a)
-
-#define SAVE_AND_DISABLE_INTS(a,b) { \
-       /* printk("get_lock: 0x%x,%4d,%s\n",(int)a,__LINE__,__FILE__);*/ \
-       spin_lock_irqsave(a,b); \
-}
-
-#define RESTORE_INTS(a,b) { \
-       /* printk("rel_lock: 0x%x,%4d,%s\n",(int)a,__LINE__,__FILE__);*/ \
-       spin_unlock_irqrestore(a,b); \
-}
-
-#define READ_LOCK_IRQSAVE(a,b) { \
-       /* printk("get_read_lock: 0x%x,%4d,%s\n",(int)a,__LINE__,__FILE__);*/ \
-       read_lock_irqsave(a,b); \
-}
-
-#define READ_UNLOCK_IRQRESTORE(a,b) { \
-       /* printk("rel_read_lock: 0x%x,%4d,%s\n",(int)a,__LINE__,__FILE__);*/ \
-       read_unlock_irqrestore(a,b); \
-}
-
-#define WRITE_LOCK_IRQSAVE(a,b) { \
-       /* printk("get_write_lock: 0x%x,%4d,%s\n",(int)a,__LINE__,__FILE__);*/ \
-       write_lock_irqsave(a,b); \
-}
-
-#define WRITE_UNLOCK_IRQRESTORE(a,b) { \
-       /* printk("rel_write_lock: 0x%x,%4d,%s\n",(int)a,__LINE__,__FILE__);*/ \
-       write_unlock_irqrestore(a,b); \
-}
-
-
-//------------------------------------------------------------------------------
-// Hardware-delay loop
-//
-// Probably used in only one place (see i2ellis.c) but this helps keep things
-// together. Note we have unwound the IN instructions. On machines with a
-// reasonable cache, the eight instructions (1 byte each) should fit in cache
-// nicely, and on un-cached machines, the code-fetch would tend not to dominate.
-// Note that cx is shifted so that "count" still reflects the total number of
-// iterations assuming no unwinding.
-//------------------------------------------------------------------------------
-
-//#define  DELAY1MS(port,count,label)
-
-//------------------------------------------------------------------------------
-// Macros to switch to a new stack, saving stack pointers, and to restore the
-// old stack (Used, for example, in i2lib.c) "heap" is the address of some
-// buffer which will become the new stack (working down from highest address).
-// The two words at the two lowest addresses in this stack are for storing the
-// SS and SP.
-//------------------------------------------------------------------------------
-
-//#define  TO_NEW_STACK(heap,size)
-//#define  TO_OLD_STACK(heap)
-
-//------------------------------------------------------------------------------
-// Macros to save the original IRQ vectors and masks, and to patch in new ones.
-//------------------------------------------------------------------------------
-
-//#define  SAVE_IRQ_MASKS(dest)
-//#define  WRITE_IRQ_MASKS(src)
-//#define  SAVE_IRQ_VECTOR(value,dest)
-//#define  WRITE_IRQ_VECTOR(value,src)
-
-//------------------------------------------------------------------------------
-// Macro to copy data from one far pointer to another.
-//------------------------------------------------------------------------------
-
-#define  I2_MOVE_DATA(fpSource,fpDest,count) memmove(fpDest,fpSource,count);
-
-//------------------------------------------------------------------------------
-// Macros to issue eoi's to host interrupt control (IBM AT 8259-style).
-//------------------------------------------------------------------------------
-
-//#define MASTER_EOI
-//#define SLAVE_EOI
-
-#endif   /* I2OS_H */
-
-
index b1d6cad84282e3960f974c9d41df0a4ed8c64500..70957acaa960ac3bcdefc2a8faa6e05aa7055502 100644 (file)
  *****************/
 
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
-static int ip2_read_procmem(char *, char **, off_t, int);
+static const struct file_operations ip2mem_proc_fops;
 static int ip2_read_proc(char *, char **, off_t, int, int *, void * );
 
 /********************/
@@ -168,7 +169,7 @@ static int Fip_firmware_size;
 static int  ip2_open(PTTY, struct file *);
 static void ip2_close(PTTY, struct file *);
 static int  ip2_write(PTTY, const unsigned char *, int);
-static void ip2_putchar(PTTY, unsigned char);
+static int  ip2_putchar(PTTY, unsigned char);
 static void ip2_flush_chars(PTTY);
 static int  ip2_write_room(PTTY);
 static int  ip2_chars_in_buf(PTTY);
@@ -354,14 +355,15 @@ have_requested_irq( char irq )
 /* the driver initialisation function and returns what it returns.            */
 /******************************************************************************/
 #ifdef MODULE
-int
-init_module(void)
+static int __init
+ip2_init_module(void)
 {
 #ifdef IP2DEBUG_INIT
        printk (KERN_DEBUG "Loading module ...\n" );
 #endif
     return 0;
 }
+module_init(ip2_init_module);
 #endif /* MODULE */
 
 /******************************************************************************/
@@ -380,8 +382,8 @@ init_module(void)
 /* driver should be returned since it may be unloaded from memory.            */
 /******************************************************************************/
 #ifdef MODULE
-void
-cleanup_module(void)
+void __exit
+ip2_cleanup_module(void)
 {
        int err;
        int i;
@@ -423,7 +425,7 @@ cleanup_module(void)
        }
        put_tty_driver(ip2_tty_driver);
        unregister_chrdev(IP2_IPL_MAJOR, pcIpl);
-       remove_proc_entry("ip2mem", &proc_root);
+       remove_proc_entry("ip2mem", NULL);
 
        // free memory
        for (i = 0; i < IP2_MAX_BOARDS; i++) {
@@ -451,6 +453,7 @@ cleanup_module(void)
        printk (KERN_DEBUG "IP2 Unloaded\n" );
 #endif
 }
+module_exit(ip2_cleanup_module);
 #endif /* MODULE */
 
 static const struct tty_operations ip2_ops = {
@@ -695,7 +698,7 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
                }
        }
        /* Register the read_procmem thing */
-       if (!create_proc_info_entry("ip2mem",0,&proc_root,ip2_read_procmem)) {
+       if (!proc_create("ip2mem",0,NULL,&ip2mem_proc_fops)) {
                printk(KERN_ERR "IP2: failed to register read_procmem\n");
        } else {
 
@@ -1049,9 +1052,9 @@ set_irq( int boardnum, int boardIrq )
         * Write to FIFO; don't bother to adjust fifo capacity for this, since
         * board will respond almost immediately after SendMail hit.
         */
-       WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags);
+       write_lock_irqsave(&pB->write_fifo_spinlock, flags);
        iiWriteBuf(pB, tempCommand, 4);
-       WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags);
+       write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
        pB->i2eUsingIrq = boardIrq;
        pB->i2eOutMailWaiting |= MB_OUT_STUFFED;
 
@@ -1069,9 +1072,9 @@ set_irq( int boardnum, int boardIrq )
        (CMD_OF(tempCommand))[4] = 64;  // chars
 
        (CMD_OF(tempCommand))[5] = 87;  // HW_TEST
-       WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags);
+       write_lock_irqsave(&pB->write_fifo_spinlock, flags);
        iiWriteBuf(pB, tempCommand, 8);
-       WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags);
+       write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
 
        CHANNEL_OF(tempCommand) = 0;
        PTYPE_OF(tempCommand) = PTYPE_BYPASS;
@@ -1086,9 +1089,9 @@ set_irq( int boardnum, int boardIrq )
        CMD_COUNT_OF(tempCommand) = 2;
        (CMD_OF(tempCommand))[0] = 44;  /* get ping */
        (CMD_OF(tempCommand))[1] = 200; /* 200 ms */
-       WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags);
+       write_lock_irqsave(&pB->write_fifo_spinlock, flags);
        iiWriteBuf(pB, tempCommand, 4);
-       WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags);
+       write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
 #endif
 
        iiEnableMailIrq(pB);
@@ -1267,12 +1270,12 @@ static void do_input(struct work_struct *work)
 
        // Data input
        if ( pCh->pTTY != NULL ) {
-               READ_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags)
+               read_lock_irqsave(&pCh->Ibuf_spinlock, flags);
                if (!pCh->throttled && (pCh->Ibuf_stuff != pCh->Ibuf_strip)) {
-                       READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags)
+                       read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
                        i2Input( pCh );
                } else
-                       READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags)
+                       read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
        } else {
                ip2trace(CHANN, ITRC_INPUT, 22, 0 );
 
@@ -1613,10 +1616,8 @@ ip2_close( PTTY tty, struct file *pFile )
 
        serviceOutgoingFifo ( pCh->pMyBord );
 
-       if ( tty->driver->flush_buffer ) 
-               tty->driver->flush_buffer(tty);
-       if ( tty->ldisc.flush_buffer )  
-               tty->ldisc.flush_buffer(tty);
+       tty_ldisc_flush(tty);
+       tty_driver_flush_buffer(tty);
        tty->closing = 0;
        
        pCh->pTTY = NULL;
@@ -1716,9 +1717,9 @@ ip2_write( PTTY tty, const unsigned char *pData, int count)
        ip2_flush_chars( tty );
 
        /* This is the actual move bit. Make sure it does what we need!!!!! */
-       WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
+       write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
        bytesSent = i2Output( pCh, pData, count);
-       WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
+       write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
 
        ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent );
 
@@ -1735,7 +1736,7 @@ ip2_write( PTTY tty, const unsigned char *pData, int count)
 /*                                                                            */
 /*                                                                            */
 /******************************************************************************/
-static void
+static int
 ip2_putchar( PTTY tty, unsigned char ch )
 {
        i2ChanStrPtr  pCh = tty->driver_data;
@@ -1743,13 +1744,14 @@ ip2_putchar( PTTY tty, unsigned char ch )
 
 //     ip2trace (CHANN, ITRC_PUTC, ITRC_ENTER, 1, ch );
 
-       WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
+       write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
        pCh->Pbuf[pCh->Pbuf_stuff++] = ch;
        if ( pCh->Pbuf_stuff == sizeof pCh->Pbuf ) {
-               WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
+               write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
                ip2_flush_chars( tty );
        } else
-               WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
+               write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
+       return 1;
 
 //     ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch );
 }
@@ -1769,7 +1771,7 @@ ip2_flush_chars( PTTY tty )
        i2ChanStrPtr  pCh = tty->driver_data;
        unsigned long flags;
 
-       WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
+       write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
        if ( pCh->Pbuf_stuff ) {
 
 //             ip2trace (CHANN, ITRC_PUTC, 10, 1, strip );
@@ -1783,7 +1785,7 @@ ip2_flush_chars( PTTY tty )
                }
                pCh->Pbuf_stuff -= strip;
        }
-       WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
+       write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
 }
 
 /******************************************************************************/
@@ -1801,9 +1803,9 @@ ip2_write_room ( PTTY tty )
        i2ChanStrPtr  pCh = tty->driver_data;
        unsigned long flags;
 
-       READ_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
+       read_lock_irqsave(&pCh->Pbuf_spinlock, flags);
        bytesFree = i2OutputFree( pCh ) - pCh->Pbuf_stuff;
-       READ_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
+       read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
 
        ip2trace (CHANN, ITRC_WRITE, 11, 1, bytesFree );
 
@@ -1833,12 +1835,12 @@ ip2_chars_in_buf ( PTTY tty )
                                 pCh->Obuf_char_count + pCh->Pbuf_stuff,
                                 pCh->Obuf_char_count, pCh->Pbuf_stuff );
 #endif
-       READ_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags);
+       read_lock_irqsave(&pCh->Obuf_spinlock, flags);
        rc =  pCh->Obuf_char_count;
-       READ_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags);
-       READ_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
+       read_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
+       read_lock_irqsave(&pCh->Pbuf_spinlock, flags);
        rc +=  pCh->Pbuf_stuff;
-       READ_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
+       read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
        return rc;
 }
 
@@ -1862,9 +1864,9 @@ ip2_flush_buffer( PTTY tty )
 #ifdef IP2DEBUG_WRITE
        printk (KERN_DEBUG "IP2: flush buffer\n" );
 #endif
-       WRITE_LOCK_IRQSAVE(&pCh->Pbuf_spinlock,flags);
+       write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
        pCh->Pbuf_stuff = 0;
-       WRITE_UNLOCK_IRQRESTORE(&pCh->Pbuf_spinlock,flags);
+       write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
        i2FlushOutput( pCh );
        ip2_owake(tty);
 
@@ -1950,15 +1952,15 @@ ip2_unthrottle ( PTTY tty )
        pCh->throttled = 0;
        i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME);
        serviceOutgoingFifo( pCh->pMyBord );
-       READ_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags)
+       read_lock_irqsave(&pCh->Ibuf_spinlock, flags);
        if ( pCh->Ibuf_stuff != pCh->Ibuf_strip ) {
-               READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags)
+               read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
 #ifdef IP2DEBUG_READ
                printk (KERN_DEBUG "i2Input called from unthrottle\n" );
 #endif
                i2Input( pCh );
        } else
-               READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags)
+               read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
 }
 
 static void
@@ -2201,9 +2203,9 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
         * for masking). Caller should use TIOCGICOUNT to see which one it was
         */
        case TIOCMIWAIT:
-               WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock, flags);
+               write_lock_irqsave(&pB->read_fifo_spinlock, flags);
                cprev = pCh->icount;     /* note the counters on entry */
-               WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock, flags);
+               write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
                i2QueueCommands(PTYPE_BYPASS, pCh, 100, 4, 
                                                CMD_DCD_REP, CMD_CTS_REP, CMD_DSR_REP, CMD_RI_REP);
                init_waitqueue_entry(&wait, current);
@@ -2223,9 +2225,9 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
                                rc = -ERESTARTSYS;
                                break;
                        }
-                       WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock, flags);
+                       write_lock_irqsave(&pB->read_fifo_spinlock, flags);
                        cnow = pCh->icount; /* atomic copy */
-                       WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock, flags);
+                       write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
                        if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
                                cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
                                rc =  -EIO; /* no change => rc */
@@ -2263,9 +2265,9 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
        case TIOCGICOUNT:
                ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc );
 
-               WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock, flags);
+               write_lock_irqsave(&pB->read_fifo_spinlock, flags);
                cnow = pCh->icount;
-               WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock, flags);
+               write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
                p_cuser = argp;
                rc = put_user(cnow.cts, &p_cuser->cts);
                rc = put_user(cnow.dsr, &p_cuser->dsr);
@@ -2871,7 +2873,7 @@ ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg )
                case 65:        /* Board  - ip2stat */
                        if ( pB ) {
                                rc = copy_to_user(argp, pB, sizeof(i2eBordStr));
-                               rc = put_user(INB(pB->i2eStatus),
+                               rc = put_user(inb(pB->i2eStatus),
                                        (ULONG __user *)(arg + (ULONG)(&pB->i2eStatus) - (ULONG)pB ) );
                        } else {
                                rc = -ENODEV;
@@ -2967,65 +2969,61 @@ ip2_ipl_open( struct inode *pInode, struct file *pFile )
        }
        return 0;
 }
-/******************************************************************************/
-/* Function:   ip2_read_procmem                                               */
-/* Parameters:                                                                */
-/*                                                                            */
-/* Returns: Length of output                                                  */
-/*                                                                            */
-/* Description:                                                               */
-/*   Supplies some driver operating parameters                                */
-/*     Not real useful unless your debugging the fifo                                                    */
-/*                                                                            */
-/******************************************************************************/
-
-#define LIMIT  (PAGE_SIZE - 120)
 
 static int
-ip2_read_procmem(char *buf, char **start, off_t offset, int len)
+proc_ip2mem_show(struct seq_file *m, void *v)
 {
        i2eBordStrPtr  pB;
        i2ChanStrPtr  pCh;
        PTTY tty;
        int i;
 
-       len = 0;
-
 #define FMTLINE        "%3d: 0x%08x 0x%08x 0%011o 0%011o\n"
 #define FMTLIN2        "     0x%04x 0x%04x tx flow 0x%x\n"
 #define FMTLIN3        "     0x%04x 0x%04x rc flow\n"
 
-       len += sprintf(buf+len,"\n");
+       seq_printf(m,"\n");
 
        for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
                pB = i2BoardPtrTable[i];
                if ( pB ) {
-                       len += sprintf(buf+len,"board %d:\n",i);
-                       len += sprintf(buf+len,"\tFifo rem: %d mty: %x outM %x\n",
+                       seq_printf(m,"board %d:\n",i);
+                       seq_printf(m,"\tFifo rem: %d mty: %x outM %x\n",
                                pB->i2eFifoRemains,pB->i2eWaitingForEmptyFifo,pB->i2eOutMailWaiting);
                }
        }
 
-       len += sprintf(buf+len,"#: tty flags, port flags,     cflags,     iflags\n");
+       seq_printf(m,"#: tty flags, port flags,     cflags,     iflags\n");
        for (i=0; i < IP2_MAX_PORTS; i++) {
-               if (len > LIMIT)
-                       break;
                pCh = DevTable[i];
                if (pCh) {
                        tty = pCh->pTTY;
                        if (tty && tty->count) {
-                               len += sprintf(buf+len,FMTLINE,i,(int)tty->flags,pCh->flags,
+                               seq_printf(m,FMTLINE,i,(int)tty->flags,pCh->flags,
                                                                        tty->termios->c_cflag,tty->termios->c_iflag);
 
-                               len += sprintf(buf+len,FMTLIN2,
+                               seq_printf(m,FMTLIN2,
                                                pCh->outfl.asof,pCh->outfl.room,pCh->channelNeeds);
-                               len += sprintf(buf+len,FMTLIN3,pCh->infl.asof,pCh->infl.room);
+                               seq_printf(m,FMTLIN3,pCh->infl.asof,pCh->infl.room);
                        }
                }
        }
-       return len;
+       return 0;
+}
+
+static int proc_ip2mem_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, proc_ip2mem_show, NULL);
 }
 
+static const struct file_operations ip2mem_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = proc_ip2mem_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
 /*
  * This is the handler for /proc/tty/driver/ip2
  *
index 553f0a408edadbc0c0835880410625ec7fae599b..eb8a1a8c188e482571a185488f60884c91c9878e 100644 (file)
@@ -9,7 +9,3 @@ obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o
 obj-$(CONFIG_IPMI_SI) += ipmi_si.o
 obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o
 obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o
-
-ipmi_si.o:     $(ipmi_si-objs)
-       $(LD) -r -o $@ $(ipmi_si-objs)
-
index e736119b64970ab6175c161e91a95d4412197bb8..7b98c067190a01917e31b1189feba430c1f1c5e9 100644 (file)
 #define BT_DEBUG_ENABLE        1       /* Generic messages */
 #define BT_DEBUG_MSG   2       /* Prints all request/response buffers */
 #define BT_DEBUG_STATES        4       /* Verbose look at state changes */
-/* BT_DEBUG_OFF must be zero to correspond to the default uninitialized
-   value */
+/*
+ * BT_DEBUG_OFF must be zero to correspond to the default uninitialized
+ * value
+ */
 
 static int bt_debug; /* 0 == BT_DEBUG_OFF */
 
 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
-   buffer (with a documented message of 160 bytes) so go for the max.
-   Since the Open IPMI architecture is single-message oriented at this
-   stage, the queue depth of BT is of no concern. */
+/*
+ * Typical "Get BT Capabilities" values are 2-3 retries, 5-10 seconds,
+ * and 64 byte buffers.  However, one HP implementation wants 255 bytes of
+ * buffer (with a documented message of 160 bytes) so go for the max.
+ * 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      5       /* seconds */
 #define BT_NORMAL_RETRY_LIMIT  2
 #define BT_RESET_DELAY         6       /* seconds after warm reset */
 
-/* States are written in chronological order and usually cover
-   multiple rows of the state table discussion in the IPMI spec. */
+/*
+ * States are written in chronological order and usually cover
+ * multiple rows of the state table discussion in the IPMI spec.
+ */
 
 enum bt_states {
        BT_STATE_IDLE = 0,      /* Order is critical in this list */
@@ -76,10 +82,12 @@ enum bt_states {
        BT_STATE_LONG_BUSY      /* BT doesn't get hosed :-) */
 };
 
-/* Macros seen at the end of state "case" blocks.  They help with legibility
-   and debugging. */
+/*
+ * Macros seen at the end of state "case" blocks.  They help with legibility
+ * and debugging.
+ */
 
-#define BT_STATE_CHANGE(X,Y) { bt->state = X; return Y; }
+#define BT_STATE_CHANGE(X, Y) { bt->state = X; return Y; }
 
 #define BT_SI_SM_RETURN(Y)   { last_printed = BT_STATE_PRINTME; return Y; }
 
@@ -110,11 +118,13 @@ struct si_sm_data {
 #define BT_H_BUSY      0x40
 #define BT_B_BUSY      0x80
 
-/* Some bits are toggled on each write: write once to set it, once
-   more to clear it; writing a zero does nothing.  To absolutely
-   clear it, check its state and write if set.  This avoids the "get
-   current then use as mask" scheme to modify one bit.  Note that the
-   variable "bt" is hardcoded into these macros. */
+/*
+ * Some bits are toggled on each write: write once to set it, once
+ * more to clear it; writing a zero does nothing.  To absolutely
+ * clear it, check its state and write if set.  This avoids the "get
+ * current then use as mask" scheme to modify one bit.  Note that the
+ * variable "bt" is hardcoded into these macros.
+ */
 
 #define BT_STATUS      bt->io->inputb(bt->io, 0)
 #define BT_CONTROL(x)  bt->io->outputb(bt->io, 0, x)
@@ -125,8 +135,10 @@ struct si_sm_data {
 #define BT_INTMASK_R   bt->io->inputb(bt->io, 2)
 #define BT_INTMASK_W(x)        bt->io->outputb(bt->io, 2, x)
 
-/* Convenience routines for debugging.  These are not multi-open safe!
-   Note the macros have hardcoded variables in them. */
+/*
+ * Convenience routines for debugging.  These are not multi-open safe!
+ * Note the macros have hardcoded variables in them.
+ */
 
 static char *state2txt(unsigned char state)
 {
@@ -182,7 +194,8 @@ static char *status2txt(unsigned char status)
 static unsigned int bt_init_data(struct si_sm_data *bt, struct si_sm_io *io)
 {
        memset(bt, 0, sizeof(struct si_sm_data));
-       if (bt->io != io) {             /* external: one-time only things */
+       if (bt->io != io) {
+               /* external: one-time only things */
                bt->io = io;
                bt->seq = 0;
        }
@@ -229,7 +242,7 @@ static int bt_start_transaction(struct si_sm_data *bt,
                printk(KERN_WARNING "BT: +++++++++++++++++ New command\n");
                printk(KERN_WARNING "BT: NetFn/LUN CMD [%d data]:", size - 2);
                for (i = 0; i < size; i ++)
-                       printk (" %02x", data[i]);
+                       printk(" %02x", data[i]);
                printk("\n");
        }
        bt->write_data[0] = size + 1;   /* all data plus seq byte */
@@ -246,8 +259,10 @@ static int bt_start_transaction(struct si_sm_data *bt,
        return 0;
 }
 
-/* After the upper state machine has been told SI_SM_TRANSACTION_COMPLETE
-   it calls this.  Strip out the length and seq bytes. */
+/*
+ * After the upper state machine has been told SI_SM_TRANSACTION_COMPLETE
+ * it calls this.  Strip out the length and seq bytes.
+ */
 
 static int bt_get_result(struct si_sm_data *bt,
                         unsigned char *data,
@@ -269,10 +284,10 @@ static int bt_get_result(struct si_sm_data *bt,
                memcpy(data + 2, bt->read_data + 4, msg_len - 2);
 
        if (bt_debug & BT_DEBUG_MSG) {
-               printk (KERN_WARNING "BT: result %d bytes:", msg_len);
+               printk(KERN_WARNING "BT: result %d bytes:", msg_len);
                for (i = 0; i < msg_len; i++)
                        printk(" %02x", data[i]);
-               printk ("\n");
+               printk("\n");
        }
        return msg_len;
 }
@@ -292,8 +307,10 @@ static void reset_flags(struct si_sm_data *bt)
        BT_INTMASK_W(BT_BMC_HWRST);
 }
 
-/* Get rid of an unwanted/stale response.  This should only be needed for
-   BMCs that support multiple outstanding requests. */
+/*
+ * Get rid of an unwanted/stale response.  This should only be needed for
+ * BMCs that support multiple outstanding requests.
+ */
 
 static void drain_BMC2HOST(struct si_sm_data *bt)
 {
@@ -326,8 +343,8 @@ static inline void write_all_bytes(struct si_sm_data *bt)
                printk(KERN_WARNING "BT: write %d bytes seq=0x%02X",
                        bt->write_count, bt->seq);
                for (i = 0; i < bt->write_count; i++)
-                       printk (" %02x", bt->write_data[i]);
-               printk ("\n");
+                       printk(" %02x", bt->write_data[i]);
+               printk("\n");
        }
        for (i = 0; i < bt->write_count; i++)
                HOST2BMC(bt->write_data[i]);
@@ -337,8 +354,10 @@ static inline int read_all_bytes(struct si_sm_data *bt)
 {
        unsigned char i;
 
-       /* length is "framing info", minimum = 4: NetFn, Seq, Cmd, cCode.
-          Keep layout of first four bytes aligned with write_data[] */
+       /*
+        * length is "framing info", minimum = 4: NetFn, Seq, Cmd, cCode.
+        * Keep layout of first four bytes aligned with write_data[]
+        */
 
        bt->read_data[0] = BMC2HOST;
        bt->read_count = bt->read_data[0];
@@ -362,8 +381,8 @@ static inline int read_all_bytes(struct si_sm_data *bt)
                if (max > 16)
                        max = 16;
                for (i = 0; i < max; i++)
-                       printk (" %02x", bt->read_data[i]);
-               printk ("%s\n", bt->read_count == max ? "" : " ...");
+                       printk(KERN_CONT " %02x", bt->read_data[i]);
+               printk(KERN_CONT "%s\n", bt->read_count == max ? "" : " ...");
        }
 
        /* per the spec, the (NetFn[1], Seq[2], Cmd[3]) tuples must match */
@@ -402,8 +421,10 @@ static enum si_sm_result error_recovery(struct si_sm_data *bt,
        printk(KERN_WARNING "IPMI BT: %s in %s %s ",    /* open-ended line */
                reason, STATE2TXT, STATUS2TXT);
 
-       /* Per the IPMI spec, retries are based on the sequence number
-          known only to this module, so manage a restart here. */
+       /*
+        * Per the IPMI spec, retries are based on the sequence number
+        * known only to this module, so manage a restart here.
+        */
        (bt->error_retries)++;
        if (bt->error_retries < bt->BT_CAP_retries) {
                printk("%d retries left\n",
@@ -412,8 +433,8 @@ static enum si_sm_result error_recovery(struct si_sm_data *bt,
                return SI_SM_CALL_WITHOUT_DELAY;
        }
 
-       printk("failed %d retries, sending error response\n",
-               bt->BT_CAP_retries);
+       printk(KERN_WARNING "failed %d retries, sending error response\n",
+              bt->BT_CAP_retries);
        if (!bt->nonzero_status)
                printk(KERN_ERR "IPMI BT: stuck, try power cycle\n");
 
@@ -424,8 +445,10 @@ static enum si_sm_result error_recovery(struct si_sm_data *bt,
                return SI_SM_CALL_WITHOUT_DELAY;
        }
 
-       /* Concoct a useful error message, set up the next state, and
-          be done with this sequence. */
+       /*
+        * Concoct a useful error message, set up the next state, and
+        * be done with this sequence.
+        */
 
        bt->state = BT_STATE_IDLE;
        switch (cCode) {
@@ -461,10 +484,12 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
                last_printed = bt->state;
        }
 
-       /* Commands that time out may still (eventually) provide a response.
-          This stale response will get in the way of a new response so remove
-          it if possible (hopefully during IDLE).  Even if it comes up later
-          it will be rejected by its (now-forgotten) seq number. */
+       /*
+        * Commands that time out may still (eventually) provide a response.
+        * This stale response will get in the way of a new response so remove
+        * it if possible (hopefully during IDLE).  Even if it comes up later
+        * it will be rejected by its (now-forgotten) seq number.
+        */
 
        if ((bt->state < BT_STATE_WRITE_BYTES) && (status & BT_B2H_ATN)) {
                drain_BMC2HOST(bt);
@@ -472,7 +497,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
        }
 
        if ((bt->state != BT_STATE_IDLE) &&
-           (bt->state <  BT_STATE_PRINTME)) {          /* check timeout */
+           (bt->state <  BT_STATE_PRINTME)) {
+               /* check timeout */
                bt->timeout -= time;
                if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1))
                        return error_recovery(bt,
@@ -482,8 +508,10 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
 
        switch (bt->state) {
 
-       /* Idle state first checks for asynchronous messages from another
-          channel, then does some opportunistic housekeeping. */
+       /*
+        * Idle state first checks for asynchronous messages from another
+        * channel, then does some opportunistic housekeeping.
+        */
 
        case BT_STATE_IDLE:
                if (status & BT_SMS_ATN) {
@@ -531,16 +559,19 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
                        BT_SI_SM_RETURN(SI_SM_CALL_WITH_DELAY);
                BT_CONTROL(BT_H_BUSY);          /* set */
 
-               /* Uncached, ordered writes should just proceeed serially but
-                  some BMCs don't clear B2H_ATN with one hit.  Fast-path a
-                  workaround without too much penalty to the general case. */
+               /*
+                * Uncached, ordered writes should just proceeed serially but
+                * some BMCs don't clear B2H_ATN with one hit.  Fast-path a
+                * workaround without too much penalty to the general case.
+                */
 
                BT_CONTROL(BT_B2H_ATN);         /* clear it to ACK the BMC */
                BT_STATE_CHANGE(BT_STATE_CLEAR_B2H,
                                SI_SM_CALL_WITHOUT_DELAY);
 
        case BT_STATE_CLEAR_B2H:
-               if (status & BT_B2H_ATN) {      /* keep hitting it */
+               if (status & BT_B2H_ATN) {
+                       /* keep hitting it */
                        BT_CONTROL(BT_B2H_ATN);
                        BT_SI_SM_RETURN(SI_SM_CALL_WITH_DELAY);
                }
@@ -548,7 +579,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
                                SI_SM_CALL_WITHOUT_DELAY);
 
        case BT_STATE_READ_BYTES:
-               if (!(status & BT_H_BUSY))      /* check in case of retry */
+               if (!(status & BT_H_BUSY))
+                       /* check in case of retry */
                        BT_CONTROL(BT_H_BUSY);
                BT_CONTROL(BT_CLR_RD_PTR);      /* start of BMC2HOST buffer */
                i = read_all_bytes(bt);         /* true == packet seq match */
@@ -599,8 +631,10 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
                BT_STATE_CHANGE(BT_STATE_XACTION_START,
                                SI_SM_CALL_WITH_DELAY);
 
-       /* Get BT Capabilities, using timing of upper level state machine.
-          Set outreqs to prevent infinite loop on timeout. */
+       /*
+        * Get BT Capabilities, using timing of upper level state machine.
+        * Set outreqs to prevent infinite loop on timeout.
+        */
        case BT_STATE_CAPABILITIES_BEGIN:
                bt->BT_CAP_outreqs = 1;
                {
@@ -638,10 +672,12 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
 
 static int bt_detect(struct si_sm_data *bt)
 {
-       /* It's impossible for the BT status and interrupt registers to be
-          all 1's, (assuming a properly functioning, self-initialized BMC)
-          but that's what you get from reading a bogus address, so we
-          test that first.  The calling routine uses negative logic. */
+       /*
+        * It's impossible for the BT status and interrupt registers to be
+        * all 1's, (assuming a properly functioning, self-initialized BMC)
+        * but that's what you get from reading a bogus address, so we
+        * test that first.  The calling routine uses negative logic.
+        */
 
        if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF))
                return 1;
@@ -658,8 +694,7 @@ static int bt_size(void)
        return sizeof(struct si_sm_data);
 }
 
-struct si_sm_handlers bt_smi_handlers =
-{
+struct si_sm_handlers bt_smi_handlers = {
        .init_data              = bt_init_data,
        .start_transaction      = bt_start_transaction,
        .get_result             = bt_get_result,
index c1b8228cb7b685c619d437fac98f01ef68169437..80704875794c38795505f945262448bb6f43cb25 100644 (file)
@@ -60,37 +60,58 @@ MODULE_PARM_DESC(kcs_debug, "debug bitmask, 1=enable, 2=messages, 4=states");
 
 /* The states the KCS driver may be in. */
 enum kcs_states {
-       KCS_IDLE,               /* The KCS interface is currently
-                                   doing nothing. */
-       KCS_START_OP,           /* We are starting an operation.  The
-                                  data is in the output buffer, but
-                                  nothing has been done to the
-                                  interface yet.  This was added to
-                                  the state machine in the spec to
-                                  wait for the initial IBF. */
-       KCS_WAIT_WRITE_START,   /* We have written a write cmd to the
-                                  interface. */
-       KCS_WAIT_WRITE,         /* We are writing bytes to the
-                                   interface. */
-       KCS_WAIT_WRITE_END,     /* We have written the write end cmd
-                                   to the interface, and still need to
-                                   write the last byte. */
-       KCS_WAIT_READ,          /* We are waiting to read data from
-                                  the interface. */
-       KCS_ERROR0,             /* State to transition to the error
-                                  handler, this was added to the
-                                  state machine in the spec to be
-                                  sure IBF was there. */
-       KCS_ERROR1,             /* First stage error handler, wait for
-                                   the interface to respond. */
-       KCS_ERROR2,             /* The abort cmd has been written,
-                                  wait for the interface to
-                                  respond. */
-       KCS_ERROR3,             /* We wrote some data to the
-                                  interface, wait for it to switch to
-                                  read mode. */
-       KCS_HOSED               /* The hardware failed to follow the
-                                  state machine. */
+       /* The KCS interface is currently doing nothing. */
+       KCS_IDLE,
+
+       /*
+        * We are starting an operation.  The data is in the output
+        * buffer, but nothing has been done to the interface yet.  This
+        * was added to the state machine in the spec to wait for the
+        * initial IBF.
+        */
+       KCS_START_OP,
+
+       /* We have written a write cmd to the interface. */
+       KCS_WAIT_WRITE_START,
+
+       /* We are writing bytes to the interface. */
+       KCS_WAIT_WRITE,
+
+       /*
+        * We have written the write end cmd to the interface, and
+        * still need to write the last byte.
+        */
+       KCS_WAIT_WRITE_END,
+
+       /* We are waiting to read data from the interface. */
+       KCS_WAIT_READ,
+
+       /*
+        * State to transition to the error handler, this was added to
+        * the state machine in the spec to be sure IBF was there.
+        */
+       KCS_ERROR0,
+
+       /*
+        * First stage error handler, wait for the interface to
+        * respond.
+        */
+       KCS_ERROR1,
+
+       /*
+        * The abort cmd has been written, wait for the interface to
+        * respond.
+        */
+       KCS_ERROR2,
+
+       /*
+        * We wrote some data to the interface, wait for it to switch
+        * to read mode.
+        */
+       KCS_ERROR3,
+
+       /* The hardware failed to follow the state machine. */
+       KCS_HOSED
 };
 
 #define MAX_KCS_READ_SIZE IPMI_MAX_MSG_LENGTH
@@ -102,8 +123,7 @@ enum kcs_states {
 #define MAX_ERROR_RETRIES 10
 #define ERROR0_OBF_WAIT_JIFFIES (2*HZ)
 
-struct si_sm_data
-{
+struct si_sm_data {
        enum kcs_states  state;
        struct si_sm_io *io;
        unsigned char    write_data[MAX_KCS_WRITE_SIZE];
@@ -187,7 +207,8 @@ static inline void start_error_recovery(struct si_sm_data *kcs, char *reason)
        (kcs->error_retries)++;
        if (kcs->error_retries > MAX_ERROR_RETRIES) {
                if (kcs_debug & KCS_DEBUG_ENABLE)
-                       printk(KERN_DEBUG "ipmi_kcs_sm: kcs hosed: %s\n", reason);
+                       printk(KERN_DEBUG "ipmi_kcs_sm: kcs hosed: %s\n",
+                              reason);
                kcs->state = KCS_HOSED;
        } else {
                kcs->error0_timeout = jiffies + ERROR0_OBF_WAIT_JIFFIES;
@@ -271,10 +292,9 @@ static int start_kcs_transaction(struct si_sm_data *kcs, unsigned char *data,
 
        if (kcs_debug & KCS_DEBUG_MSG) {
                printk(KERN_DEBUG "start_kcs_transaction -");
-               for (i = 0; i < size; i ++) {
+               for (i = 0; i < size; i++)
                        printk(" %02x", (unsigned char) (data [i]));
-               }
-               printk ("\n");
+               printk("\n");
        }
        kcs->error_retries = 0;
        memcpy(kcs->write_data, data, size);
@@ -305,9 +325,11 @@ static int get_kcs_result(struct si_sm_data *kcs, unsigned char *data,
                kcs->read_pos = 3;
        }
        if (kcs->truncated) {
-               /* Report a truncated error.  We might overwrite
-                  another error, but that's too bad, the user needs
-                  to know it was truncated. */
+               /*
+                * Report a truncated error.  We might overwrite
+                * another error, but that's too bad, the user needs
+                * to know it was truncated.
+                */
                data[2] = IPMI_ERR_MSG_TRUNCATED;
                kcs->truncated = 0;
        }
@@ -315,9 +337,11 @@ static int get_kcs_result(struct si_sm_data *kcs, unsigned char *data,
        return kcs->read_pos;
 }
 
-/* This implements the state machine defined in the IPMI manual, see
-   that for details on how this works.  Divide that flowchart into
-   sections delimited by "Wait for IBF" and this will become clear. */
+/*
+ * This implements the state machine defined in the IPMI manual, see
+ * that for details on how this works.  Divide that flowchart into
+ * sections delimited by "Wait for IBF" and this will become clear.
+ */
 static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
 {
        unsigned char status;
@@ -388,11 +412,12 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
                        write_next_byte(kcs);
                }
                break;
-               
+
        case KCS_WAIT_WRITE_END:
                if (state != KCS_WRITE_STATE) {
                        start_error_recovery(kcs,
-                                            "Not in write state for write end");
+                                            "Not in write state"
+                                            " for write end");
                        break;
                }
                clear_obf(kcs, status);
@@ -413,13 +438,15 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
                                return SI_SM_CALL_WITH_DELAY;
                        read_next_byte(kcs);
                } else {
-                       /* We don't implement this exactly like the state
-                          machine in the spec.  Some broken hardware
-                          does not write the final dummy byte to the
-                          read register.  Thus obf will never go high
-                          here.  We just go straight to idle, and we
-                          handle clearing out obf in idle state if it
-                          happens to come in. */
+                       /*
+                        * We don't implement this exactly like the state
+                        * machine in the spec.  Some broken hardware
+                        * does not write the final dummy byte to the
+                        * read register.  Thus obf will never go high
+                        * here.  We just go straight to idle, and we
+                        * handle clearing out obf in idle state if it
+                        * happens to come in.
+                        */
                        clear_obf(kcs, status);
                        kcs->orig_write_count = 0;
                        kcs->state = KCS_IDLE;
@@ -430,7 +457,8 @@ 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 (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);
@@ -442,7 +470,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
                write_data(kcs, 0);
                kcs->state = KCS_ERROR2;
                break;
-               
+
        case KCS_ERROR2:
                if (state != KCS_READ_STATE) {
                        start_error_recovery(kcs,
@@ -456,7 +484,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
                write_data(kcs, KCS_READ_BYTE);
                kcs->state = KCS_ERROR3;
                break;
-               
+
        case KCS_ERROR3:
                if (state != KCS_IDLE_STATE) {
                        start_error_recovery(kcs,
@@ -475,7 +503,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
                        return SI_SM_TRANSACTION_COMPLETE;
                }
                break;
-                       
+
        case KCS_HOSED:
                break;
        }
@@ -495,10 +523,12 @@ static int kcs_size(void)
 
 static int kcs_detect(struct si_sm_data *kcs)
 {
-       /* It's impossible for the KCS status register to be all 1's,
-          (assuming a properly functioning, self-initialized BMC)
-          but that's what you get from reading a bogus address, so we
-          test that first. */
+       /*
+        * It's impossible for the KCS status register to be all 1's,
+        * (assuming a properly functioning, self-initialized BMC)
+        * but that's what you get from reading a bogus address, so we
+        * test that first.
+        */
        if (read_status(kcs) == 0xff)
                return 1;
 
@@ -509,8 +539,7 @@ static void kcs_cleanup(struct si_sm_data *kcs)
 {
 }
 
-struct si_sm_handlers kcs_smi_handlers =
-{
+struct si_sm_handlers kcs_smi_handlers = {
        .init_data         = init_kcs_data,
        .start_transaction = start_kcs_transaction,
        .get_result        = get_kcs_result,
index 32b2b22996dc34efc189ccc71b5cdc2b6b3b4ba2..8a59aaa21be5c79e337802eba20cc0e5ac860f67 100644 (file)
@@ -47,7 +47,7 @@
 
 #define PFX "IPMI message handler: "
 
-#define IPMI_DRIVER_VERSION "39.1"
+#define IPMI_DRIVER_VERSION "39.2"
 
 static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
 static int ipmi_init_msghandler(void);
@@ -63,16 +63,16 @@ static struct proc_dir_entry *proc_ipmi_root;
 
 #define MAX_EVENTS_IN_QUEUE    25
 
-/* Don't let a message sit in a queue forever, always time it with at lest
-   the max message timer.  This is in milliseconds. */
+/*
+ * Don't let a message sit in a queue forever, always time it with at lest
+ * the max message timer.  This is in milliseconds.
+ */
 #define MAX_MSG_TIMEOUT                60000
 
-
 /*
  * The main "user" data structure.
  */
-struct ipmi_user
-{
+struct ipmi_user {
        struct list_head link;
 
        /* Set to "0" when the user is destroyed. */
@@ -91,8 +91,7 @@ struct ipmi_user
        int gets_events;
 };
 
-struct cmd_rcvr
-{
+struct cmd_rcvr {
        struct list_head link;
 
        ipmi_user_t   user;
@@ -106,12 +105,12 @@ struct cmd_rcvr
         * 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. */
+        * every individual deletion of a command.
+        */
        struct cmd_rcvr *next;
 };
 
-struct seq_table
-{
+struct seq_table {
        unsigned int         inuse : 1;
        unsigned int         broadcast : 1;
 
@@ -119,53 +118,60 @@ struct seq_table
        unsigned long        orig_timeout;
        unsigned int         retries_left;
 
-       /* To verify on an incoming send message response that this is
-           the message that the response is for, we keep a sequence id
-           and increment it every time we send a message. */
+       /*
+        * To verify on an incoming send message response that this is
+        * the message that the response is for, we keep a sequence id
+        * and increment it every time we send a message.
+        */
        long                 seqid;
 
-       /* This is held so we can properly respond to the message on a
-           timeout, and it is used to hold the temporary data for
-           retransmission, too. */
+       /*
+        * This is held so we can properly respond to the message on a
+        * timeout, and it is used to hold the temporary data for
+        * retransmission, too.
+        */
        struct ipmi_recv_msg *recv_msg;
 };
 
-/* Store the information in a msgid (long) to allow us to find a
-   sequence table entry from the msgid. */
+/*
+ * Store the information in a msgid (long) to allow us to find a
+ * sequence table entry from the msgid.
+ */
 #define STORE_SEQ_IN_MSGID(seq, seqid) (((seq&0xff)<<26) | (seqid&0x3ffffff))
 
 #define GET_SEQ_FROM_MSGID(msgid, seq, seqid) \
        do {                                                            \
                seq = ((msgid >> 26) & 0x3f);                           \
                seqid = (msgid & 0x3fffff);                             \
-        } while (0)
+       } while (0)
 
 #define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3fffff)
 
-struct ipmi_channel
-{
+struct ipmi_channel {
        unsigned char medium;
        unsigned char protocol;
 
-       /* My slave address.  This is initialized to IPMI_BMC_SLAVE_ADDR,
-          but may be changed by the user. */
+       /*
+        * My slave address.  This is initialized to IPMI_BMC_SLAVE_ADDR,
+        * but may be changed by the user.
+        */
        unsigned char address;
 
-       /* My LUN.  This should generally stay the SMS LUN, but just in
-          case... */
+       /*
+        * My LUN.  This should generally stay the SMS LUN, but just in
+        * case...
+        */
        unsigned char lun;
 };
 
 #ifdef CONFIG_PROC_FS
-struct ipmi_proc_entry
-{
+struct ipmi_proc_entry {
        char                   *name;
        struct ipmi_proc_entry *next;
 };
 #endif
 
-struct bmc_device
-{
+struct bmc_device {
        struct platform_device *dev;
        struct ipmi_device_id  id;
        unsigned char          guid[16];
@@ -186,10 +192,108 @@ struct bmc_device
        struct device_attribute aux_firmware_rev_attr;
 };
 
+/*
+ * Various statistics for IPMI, these index stats[] in the ipmi_smi
+ * structure.
+ */
+enum ipmi_stat_indexes {
+       /* Commands we got from the user that were invalid. */
+       IPMI_STAT_sent_invalid_commands = 0,
+
+       /* Commands we sent to the MC. */
+       IPMI_STAT_sent_local_commands,
+
+       /* Responses from the MC that were delivered to a user. */
+       IPMI_STAT_handled_local_responses,
+
+       /* Responses from the MC that were not delivered to a user. */
+       IPMI_STAT_unhandled_local_responses,
+
+       /* Commands we sent out to the IPMB bus. */
+       IPMI_STAT_sent_ipmb_commands,
+
+       /* Commands sent on the IPMB that had errors on the SEND CMD */
+       IPMI_STAT_sent_ipmb_command_errs,
+
+       /* Each retransmit increments this count. */
+       IPMI_STAT_retransmitted_ipmb_commands,
+
+       /*
+        * When a message times out (runs out of retransmits) this is
+        * incremented.
+        */
+       IPMI_STAT_timed_out_ipmb_commands,
+
+       /*
+        * This is like above, but for broadcasts.  Broadcasts are
+        * *not* included in the above count (they are expected to
+        * time out).
+        */
+       IPMI_STAT_timed_out_ipmb_broadcasts,
+
+       /* Responses I have sent to the IPMB bus. */
+       IPMI_STAT_sent_ipmb_responses,
+
+       /* The response was delivered to the user. */
+       IPMI_STAT_handled_ipmb_responses,
+
+       /* The response had invalid data in it. */
+       IPMI_STAT_invalid_ipmb_responses,
+
+       /* The response didn't have anyone waiting for it. */
+       IPMI_STAT_unhandled_ipmb_responses,
+
+       /* Commands we sent out to the IPMB bus. */
+       IPMI_STAT_sent_lan_commands,
+
+       /* Commands sent on the IPMB that had errors on the SEND CMD */
+       IPMI_STAT_sent_lan_command_errs,
+
+       /* Each retransmit increments this count. */
+       IPMI_STAT_retransmitted_lan_commands,
+
+       /*
+        * When a message times out (runs out of retransmits) this is
+        * incremented.
+        */
+       IPMI_STAT_timed_out_lan_commands,
+
+       /* Responses I have sent to the IPMB bus. */
+       IPMI_STAT_sent_lan_responses,
+
+       /* The response was delivered to the user. */
+       IPMI_STAT_handled_lan_responses,
+
+       /* The response had invalid data in it. */
+       IPMI_STAT_invalid_lan_responses,
+
+       /* The response didn't have anyone waiting for it. */
+       IPMI_STAT_unhandled_lan_responses,
+
+       /* The command was delivered to the user. */
+       IPMI_STAT_handled_commands,
+
+       /* The command had invalid data in it. */
+       IPMI_STAT_invalid_commands,
+
+       /* The command didn't have anyone waiting for it. */
+       IPMI_STAT_unhandled_commands,
+
+       /* Invalid data in an event. */
+       IPMI_STAT_invalid_events,
+
+       /* Events that were received with the proper format. */
+       IPMI_STAT_events,
+
+
+       /* This *must* remain last, add new values above this. */
+       IPMI_NUM_STATS
+};
+
+
 #define IPMI_IPMB_NUM_SEQ      64
 #define IPMI_MAX_CHANNELS       16
-struct ipmi_smi
-{
+struct ipmi_smi {
        /* What interface number are we? */
        int intf_num;
 
@@ -198,8 +302,10 @@ struct ipmi_smi
        /* Used for a list of interfaces. */
        struct list_head link;
 
-       /* The list of upper layers that are using me.  seq_lock
-        * protects this. */
+       /*
+        * The list of upper layers that are using me.  seq_lock
+        * protects this.
+        */
        struct list_head users;
 
        /* Information to supply to users. */
@@ -213,10 +319,12 @@ struct ipmi_smi
        char *my_dev_name;
        char *sysfs_name;
 
-       /* This is the lower-layer's sender routine.  Note that you
+       /*
+        * This is the lower-layer's sender routine.  Note that you
         * must either be holding the ipmi_interfaces_mutex or be in
         * an umpreemptible region to use this.  You must fetch the
-        * value into a local variable and make sure it is not NULL. */
+        * value into a local variable and make sure it is not NULL.
+        */
        struct ipmi_smi_handlers *handlers;
        void                     *send_info;
 
@@ -229,34 +337,45 @@ struct ipmi_smi
        /* Driver-model device for the system interface. */
        struct device          *si_dev;
 
-       /* A table of sequence numbers for this interface.  We use the
-           sequence numbers for IPMB messages that go out of the
-           interface to match them up with their responses.  A routine
-           is called periodically to time the items in this list. */
+       /*
+        * A table of sequence numbers for this interface.  We use the
+        * sequence numbers for IPMB messages that go out of the
+        * interface to match them up with their responses.  A routine
+        * is called periodically to time the items in this list.
+        */
        spinlock_t       seq_lock;
        struct seq_table seq_table[IPMI_IPMB_NUM_SEQ];
        int curr_seq;
 
-       /* Messages that were delayed for some reason (out of memory,
-           for instance), will go in here to be processed later in a
-           periodic timer interrupt. */
+       /*
+        * Messages that were delayed for some reason (out of memory,
+        * for instance), will go in here to be processed later in a
+        * periodic timer interrupt.
+        */
        spinlock_t       waiting_msgs_lock;
        struct list_head waiting_msgs;
 
-       /* The list of command receivers that are registered for commands
-          on this interface. */
+       /*
+        * The list of command receivers that are registered for commands
+        * on this interface.
+        */
        struct mutex     cmd_rcvrs_mutex;
        struct list_head cmd_rcvrs;
 
-       /* Events that were queues because no one was there to receive
-           them. */
+       /*
+        * Events that were queues because no one was there to receive
+        * them.
+        */
        spinlock_t       events_lock; /* For dealing with event stuff. */
        struct list_head waiting_events;
        unsigned int     waiting_events_count; /* How many events in queue? */
-       int              delivering_events;
+       char             delivering_events;
+       char             event_msg_printed;
 
-       /* The event receiver for my BMC, only really used at panic
-          shutdown as a place to store this. */
+       /*
+        * The event receiver for my BMC, only really used at panic
+        * shutdown as a place to store this.
+        */
        unsigned char event_receiver;
        unsigned char event_receiver_lun;
        unsigned char local_sel_device;
@@ -268,14 +387,18 @@ struct ipmi_smi
        int auto_maintenance_timeout;
        spinlock_t maintenance_mode_lock; /* Used in a timer... */
 
-       /* A cheap hack, if this is non-null and a message to an
-          interface comes in with a NULL user, call this routine with
-          it.  Note that the message will still be freed by the
-          caller.  This only works on the system interface. */
+       /*
+        * A cheap hack, if this is non-null and a message to an
+        * interface comes in with a NULL user, call this routine with
+        * it.  Note that the message will still be freed by the
+        * caller.  This only works on the system interface.
+        */
        void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_recv_msg *msg);
 
-       /* When we are scanning the channels for an SMI, this will
-          tell which channel we are scanning. */
+       /*
+        * When we are scanning the channels for an SMI, this will
+        * tell which channel we are scanning.
+        */
        int curr_channel;
 
        /* Channel information */
@@ -285,74 +408,14 @@ struct ipmi_smi
        struct proc_dir_entry *proc_dir;
        char                  proc_dir_name[10];
 
-       spinlock_t   counter_lock; /* For making counters atomic. */
-
-       /* Commands we got that were invalid. */
-       unsigned int sent_invalid_commands;
-
-       /* Commands we sent to the MC. */
-       unsigned int sent_local_commands;
-       /* Responses from the MC that were delivered to a user. */
-       unsigned int handled_local_responses;
-       /* Responses from the MC that were not delivered to a user. */
-       unsigned int unhandled_local_responses;
-
-       /* Commands we sent out to the IPMB bus. */
-       unsigned int sent_ipmb_commands;
-       /* Commands sent on the IPMB that had errors on the SEND CMD */
-       unsigned int sent_ipmb_command_errs;
-       /* Each retransmit increments this count. */
-       unsigned int retransmitted_ipmb_commands;
-       /* When a message times out (runs out of retransmits) this is
-           incremented. */
-       unsigned int timed_out_ipmb_commands;
-
-       /* This is like above, but for broadcasts.  Broadcasts are
-           *not* included in the above count (they are expected to
-           time out). */
-       unsigned int timed_out_ipmb_broadcasts;
+       atomic_t stats[IPMI_NUM_STATS];
 
-       /* Responses I have sent to the IPMB bus. */
-       unsigned int sent_ipmb_responses;
-
-       /* The response was delivered to the user. */
-       unsigned int handled_ipmb_responses;
-       /* The response had invalid data in it. */
-       unsigned int invalid_ipmb_responses;
-       /* The response didn't have anyone waiting for it. */
-       unsigned int unhandled_ipmb_responses;
-
-       /* Commands we sent out to the IPMB bus. */
-       unsigned int sent_lan_commands;
-       /* Commands sent on the IPMB that had errors on the SEND CMD */
-       unsigned int sent_lan_command_errs;
-       /* Each retransmit increments this count. */
-       unsigned int retransmitted_lan_commands;
-       /* When a message times out (runs out of retransmits) this is
-           incremented. */
-       unsigned int timed_out_lan_commands;
-
-       /* Responses I have sent to the IPMB bus. */
-       unsigned int sent_lan_responses;
-
-       /* The response was delivered to the user. */
-       unsigned int handled_lan_responses;
-       /* The response had invalid data in it. */
-       unsigned int invalid_lan_responses;
-       /* The response didn't have anyone waiting for it. */
-       unsigned int unhandled_lan_responses;
-
-       /* The command was delivered to the user. */
-       unsigned int handled_commands;
-       /* The command had invalid data in it. */
-       unsigned int invalid_commands;
-       /* The command didn't have anyone waiting for it. */
-       unsigned int unhandled_commands;
-
-       /* Invalid data in an event. */
-       unsigned int invalid_events;
-       /* Events that were received with the proper format. */
-       unsigned int events;
+       /*
+        * run_to_completion duplicate of smb_info, smi_info
+        * and ipmi_serial_info structures. Used to decrease numbers of
+        * parameters passed by "low" level IPMI code.
+        */
+       int run_to_completion;
 };
 #define to_si_intf_from_dev(device) container_of(device, struct ipmi_smi, dev)
 
@@ -368,12 +431,19 @@ static DEFINE_MUTEX(ipmidriver_mutex);
 static LIST_HEAD(ipmi_interfaces);
 static DEFINE_MUTEX(ipmi_interfaces_mutex);
 
-/* List of watchers that want to know when smi's are added and
-   deleted. */
+/*
+ * List of watchers that want to know when smi's are added and deleted.
+ */
 static LIST_HEAD(smi_watchers);
 static DEFINE_MUTEX(smi_watchers_mutex);
 
 
+#define ipmi_inc_stat(intf, stat) \
+       atomic_inc(&(intf)->stats[IPMI_STAT_ ## stat])
+#define ipmi_get_stat(intf, stat) \
+       ((unsigned int) atomic_read(&(intf)->stats[IPMI_STAT_ ## stat]))
+
+
 static void free_recv_msg_list(struct list_head *q)
 {
        struct ipmi_recv_msg *msg, *msg2;
@@ -417,10 +487,8 @@ static void clean_up_interface_data(ipmi_smi_t intf)
 
        for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) {
                if ((intf->seq_table[i].inuse)
-                   && (intf->seq_table[i].recv_msg))
-               {
+                                       && (intf->seq_table[i].recv_msg))
                        ipmi_free_recv_msg(intf->seq_table[i].recv_msg);
-               }
        }
 }
 
@@ -487,6 +555,7 @@ int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
        }
        return -ENOMEM;
 }
+EXPORT_SYMBOL(ipmi_smi_watcher_register);
 
 int ipmi_smi_watcher_unregister(struct ipmi_smi_watcher *watcher)
 {
@@ -495,6 +564,7 @@ int ipmi_smi_watcher_unregister(struct ipmi_smi_watcher *watcher)
        mutex_unlock(&smi_watchers_mutex);
        return 0;
 }
+EXPORT_SYMBOL(ipmi_smi_watcher_unregister);
 
 /*
  * Must be called with smi_watchers_mutex held.
@@ -530,8 +600,7 @@ ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2)
        }
 
        if ((addr1->addr_type == IPMI_IPMB_ADDR_TYPE)
-           || (addr1->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
-       {
+           || (addr1->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)) {
                struct ipmi_ipmb_addr *ipmb_addr1
                    = (struct ipmi_ipmb_addr *) addr1;
                struct ipmi_ipmb_addr *ipmb_addr2
@@ -559,9 +628,8 @@ ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2)
 
 int ipmi_validate_addr(struct ipmi_addr *addr, int len)
 {
-       if (len < sizeof(struct ipmi_system_interface_addr)) {
+       if (len < sizeof(struct ipmi_system_interface_addr))
                return -EINVAL;
-       }
 
        if (addr->addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) {
                if (addr->channel != IPMI_BMC_CHANNEL)
@@ -575,23 +643,21 @@ int ipmi_validate_addr(struct ipmi_addr *addr, int len)
                return -EINVAL;
 
        if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE)
-           || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
-       {
-               if (len < sizeof(struct ipmi_ipmb_addr)) {
+           || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)) {
+               if (len < sizeof(struct ipmi_ipmb_addr))
                        return -EINVAL;
-               }
                return 0;
        }
 
        if (addr->addr_type == IPMI_LAN_ADDR_TYPE) {
-               if (len < sizeof(struct ipmi_lan_addr)) {
+               if (len < sizeof(struct ipmi_lan_addr))
                        return -EINVAL;
-               }
                return 0;
        }
 
        return -EINVAL;
 }
+EXPORT_SYMBOL(ipmi_validate_addr);
 
 unsigned int ipmi_addr_length(int addr_type)
 {
@@ -599,34 +665,28 @@ unsigned int ipmi_addr_length(int addr_type)
                return sizeof(struct ipmi_system_interface_addr);
 
        if ((addr_type == IPMI_IPMB_ADDR_TYPE)
-           || (addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
-       {
+                       || (addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
                return sizeof(struct ipmi_ipmb_addr);
-       }
 
        if (addr_type == IPMI_LAN_ADDR_TYPE)
                return sizeof(struct ipmi_lan_addr);
 
        return 0;
 }
+EXPORT_SYMBOL(ipmi_addr_length);
 
 static void deliver_response(struct ipmi_recv_msg *msg)
 {
        if (!msg->user) {
                ipmi_smi_t    intf = msg->user_msg_data;
-               unsigned long flags;
 
                /* Special handling for NULL users. */
                if (intf->null_user_handler) {
                        intf->null_user_handler(intf, msg);
-                       spin_lock_irqsave(&intf->counter_lock, flags);
-                       intf->handled_local_responses++;
-                       spin_unlock_irqrestore(&intf->counter_lock, flags);
+                       ipmi_inc_stat(intf, handled_local_responses);
                } else {
                        /* No handler, so give up. */
-                       spin_lock_irqsave(&intf->counter_lock, flags);
-                       intf->unhandled_local_responses++;
-                       spin_unlock_irqrestore(&intf->counter_lock, flags);
+                       ipmi_inc_stat(intf, unhandled_local_responses);
                }
                ipmi_free_recv_msg(msg);
        } else {
@@ -646,9 +706,11 @@ deliver_err_response(struct ipmi_recv_msg *msg, int err)
        deliver_response(msg);
 }
 
-/* Find the next sequence number not being used and add the given
-   message with the given timeout to the sequence table.  This must be
-   called with the interface's seq_lock held. */
+/*
+ * Find the next sequence number not being used and add the given
+ * message with the given timeout to the sequence table.  This must be
+ * called with the interface's seq_lock held.
+ */
 static int intf_next_seq(ipmi_smi_t           intf,
                         struct ipmi_recv_msg *recv_msg,
                         unsigned long        timeout,
@@ -660,10 +722,8 @@ static int intf_next_seq(ipmi_smi_t           intf,
        int          rv = 0;
        unsigned int i;
 
-       for (i = intf->curr_seq;
-            (i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq;
-            i = (i+1)%IPMI_IPMB_NUM_SEQ)
-       {
+       for (i = intf->curr_seq; (i+1)%IPMI_IPMB_NUM_SEQ != intf->curr_seq;
+                                       i = (i+1)%IPMI_IPMB_NUM_SEQ) {
                if (!intf->seq_table[i].inuse)
                        break;
        }
@@ -671,8 +731,10 @@ static int intf_next_seq(ipmi_smi_t           intf,
        if (!intf->seq_table[i].inuse) {
                intf->seq_table[i].recv_msg = recv_msg;
 
-               /* Start with the maximum timeout, when the send response
-                  comes in we will start the real timer. */
+               /*
+                * Start with the maximum timeout, when the send response
+                * comes in we will start the real timer.
+                */
                intf->seq_table[i].timeout = MAX_MSG_TIMEOUT;
                intf->seq_table[i].orig_timeout = timeout;
                intf->seq_table[i].retries_left = retries;
@@ -685,15 +747,17 @@ static int intf_next_seq(ipmi_smi_t           intf,
        } else {
                rv = -EAGAIN;
        }
-       
+
        return rv;
 }
 
-/* Return the receive message for the given sequence number and
-   release the sequence number so it can be reused.  Some other data
-   is passed in to be sure the message matches up correctly (to help
-   guard against message coming in after their timeout and the
-   sequence number being reused). */
+/*
+ * Return the receive message for the given sequence number and
+ * release the sequence number so it can be reused.  Some other data
+ * is passed in to be sure the message matches up correctly (to help
+ * guard against message coming in after their timeout and the
+ * sequence number being reused).
+ */
 static int intf_find_seq(ipmi_smi_t           intf,
                         unsigned char        seq,
                         short                channel,
@@ -712,11 +776,9 @@ static int intf_find_seq(ipmi_smi_t           intf,
        if (intf->seq_table[seq].inuse) {
                struct ipmi_recv_msg *msg = intf->seq_table[seq].recv_msg;
 
-               if ((msg->addr.channel == channel)
-                   && (msg->msg.cmd == cmd)
-                   && (msg->msg.netfn == netfn)
-                   && (ipmi_addr_equal(addr, &(msg->addr))))
-               {
+               if ((msg->addr.channel == channel) && (msg->msg.cmd == cmd)
+                               && (msg->msg.netfn == netfn)
+                               && (ipmi_addr_equal(addr, &(msg->addr)))) {
                        *recv_msg = msg;
                        intf->seq_table[seq].inuse = 0;
                        rv = 0;
@@ -741,11 +803,12 @@ static int intf_start_seq_timer(ipmi_smi_t intf,
        GET_SEQ_FROM_MSGID(msgid, seq, seqid);
 
        spin_lock_irqsave(&(intf->seq_lock), flags);
-       /* We do this verification because the user can be deleted
-           while a message is outstanding. */
+       /*
+        * We do this verification because the user can be deleted
+        * while a message is outstanding.
+        */
        if ((intf->seq_table[seq].inuse)
-           && (intf->seq_table[seq].seqid == seqid))
-       {
+                               && (intf->seq_table[seq].seqid == seqid)) {
                struct seq_table *ent = &(intf->seq_table[seq]);
                ent->timeout = ent->orig_timeout;
                rv = 0;
@@ -770,11 +833,12 @@ static int intf_err_seq(ipmi_smi_t   intf,
        GET_SEQ_FROM_MSGID(msgid, seq, seqid);
 
        spin_lock_irqsave(&(intf->seq_lock), flags);
-       /* We do this verification because the user can be deleted
-           while a message is outstanding. */
+       /*
+        * We do this verification because the user can be deleted
+        * while a message is outstanding.
+        */
        if ((intf->seq_table[seq].inuse)
-           && (intf->seq_table[seq].seqid == seqid))
-       {
+                               && (intf->seq_table[seq].seqid == seqid)) {
                struct seq_table *ent = &(intf->seq_table[seq]);
 
                ent->inuse = 0;
@@ -800,24 +864,30 @@ int ipmi_create_user(unsigned int          if_num,
        int           rv = 0;
        ipmi_smi_t    intf;
 
-       /* There is no module usecount here, because it's not
-           required.  Since this can only be used by and called from
-           other modules, they will implicitly use this module, and
-           thus this can't be removed unless the other modules are
-           removed. */
+       /*
+        * There is no module usecount here, because it's not
+        * required.  Since this can only be used by and called from
+        * other modules, they will implicitly use this module, and
+        * thus this can't be removed unless the other modules are
+        * removed.
+        */
 
        if (handler == NULL)
                return -EINVAL;
 
-       /* Make sure the driver is actually initialized, this handles
-          problems with initialization order. */
+       /*
+        * Make sure the driver is actually initialized, this handles
+        * problems with initialization order.
+        */
        if (!initialized) {
                rv = ipmi_init_msghandler();
                if (rv)
                        return rv;
 
-               /* The init code doesn't return an error if it was turned
-                  off, but it won't initialize.  Check that. */
+               /*
+                * The init code doesn't return an error if it was turned
+                * off, but it won't initialize.  Check that.
+                */
                if (!initialized)
                        return -ENODEV;
        }
@@ -858,8 +928,10 @@ int ipmi_create_user(unsigned int          if_num,
                }
        }
 
-       /* Hold the lock so intf->handlers is guaranteed to be good
-        * until now */
+       /*
+        * Hold the lock so intf->handlers is guaranteed to be good
+        * until now
+        */
        mutex_unlock(&ipmi_interfaces_mutex);
 
        new_user->valid = 1;
@@ -876,6 +948,7 @@ out_kfree:
        kfree(new_user);
        return rv;
 }
+EXPORT_SYMBOL(ipmi_create_user);
 
 static void free_user(struct kref *ref)
 {
@@ -899,8 +972,7 @@ int ipmi_destroy_user(ipmi_user_t user)
 
        for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) {
                if (intf->seq_table[i].inuse
-                   && (intf->seq_table[i].recv_msg->user == user))
-               {
+                   && (intf->seq_table[i].recv_msg->user == user)) {
                        intf->seq_table[i].inuse = 0;
                        ipmi_free_recv_msg(intf->seq_table[i].recv_msg);
                }
@@ -943,6 +1015,7 @@ int ipmi_destroy_user(ipmi_user_t user)
 
        return 0;
 }
+EXPORT_SYMBOL(ipmi_destroy_user);
 
 void ipmi_get_version(ipmi_user_t   user,
                      unsigned char *major,
@@ -951,6 +1024,7 @@ void ipmi_get_version(ipmi_user_t   user,
        *major = user->intf->ipmi_version_major;
        *minor = user->intf->ipmi_version_minor;
 }
+EXPORT_SYMBOL(ipmi_get_version);
 
 int ipmi_set_my_address(ipmi_user_t   user,
                        unsigned int  channel,
@@ -961,6 +1035,7 @@ int ipmi_set_my_address(ipmi_user_t   user,
        user->intf->channels[channel].address = address;
        return 0;
 }
+EXPORT_SYMBOL(ipmi_set_my_address);
 
 int ipmi_get_my_address(ipmi_user_t   user,
                        unsigned int  channel,
@@ -971,6 +1046,7 @@ int ipmi_get_my_address(ipmi_user_t   user,
        *address = user->intf->channels[channel].address;
        return 0;
 }
+EXPORT_SYMBOL(ipmi_get_my_address);
 
 int ipmi_set_my_LUN(ipmi_user_t   user,
                    unsigned int  channel,
@@ -981,6 +1057,7 @@ int ipmi_set_my_LUN(ipmi_user_t   user,
        user->intf->channels[channel].lun = LUN & 0x3;
        return 0;
 }
+EXPORT_SYMBOL(ipmi_set_my_LUN);
 
 int ipmi_get_my_LUN(ipmi_user_t   user,
                    unsigned int  channel,
@@ -991,6 +1068,7 @@ int ipmi_get_my_LUN(ipmi_user_t   user,
        *address = user->intf->channels[channel].lun;
        return 0;
 }
+EXPORT_SYMBOL(ipmi_get_my_LUN);
 
 int ipmi_get_maintenance_mode(ipmi_user_t user)
 {
@@ -1075,6 +1153,11 @@ int ipmi_set_gets_events(ipmi_user_t user, int val)
                list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link)
                        list_move_tail(&msg->link, &msgs);
                intf->waiting_events_count = 0;
+               if (intf->event_msg_printed) {
+                       printk(KERN_WARNING PFX "Event queue no longer"
+                              " full\n");
+                       intf->event_msg_printed = 0;
+               }
 
                intf->delivering_events = 1;
                spin_unlock_irqrestore(&intf->events_lock, flags);
@@ -1094,6 +1177,7 @@ int ipmi_set_gets_events(ipmi_user_t user, int val)
 
        return 0;
 }
+EXPORT_SYMBOL(ipmi_set_gets_events);
 
 static struct cmd_rcvr *find_cmd_rcvr(ipmi_smi_t    intf,
                                      unsigned char netfn,
@@ -1159,6 +1243,7 @@ int ipmi_register_for_cmd(ipmi_user_t   user,
 
        return rv;
 }
+EXPORT_SYMBOL(ipmi_register_for_cmd);
 
 int ipmi_unregister_for_cmd(ipmi_user_t   user,
                            unsigned char netfn,
@@ -1196,19 +1281,13 @@ int ipmi_unregister_for_cmd(ipmi_user_t   user,
        }
        return rv;
 }
-
-void ipmi_user_set_run_to_completion(ipmi_user_t user, int val)
-{
-       ipmi_smi_t intf = user->intf;
-       if (intf->handlers)
-               intf->handlers->set_run_to_completion(intf->send_info, val);
-}
+EXPORT_SYMBOL(ipmi_unregister_for_cmd);
 
 static unsigned char
 ipmb_checksum(unsigned char *data, int size)
 {
        unsigned char csum = 0;
-       
+
        for (; size > 0; size--, data++)
                csum += *data;
 
@@ -1250,8 +1329,10 @@ static inline void format_ipmb_msg(struct ipmi_smi_msg   *smi_msg,
                = ipmb_checksum(&(smi_msg->data[i+6]),
                                smi_msg->data_size-6);
 
-       /* Add on the checksum size and the offset from the
-          broadcast. */
+       /*
+        * Add on the checksum size and the offset from the
+        * broadcast.
+        */
        smi_msg->data_size += 1 + i;
 
        smi_msg->msgid = msgid;
@@ -1287,17 +1368,21 @@ static inline void format_lan_msg(struct ipmi_smi_msg   *smi_msg,
                = ipmb_checksum(&(smi_msg->data[7]),
                                smi_msg->data_size-7);
 
-       /* Add on the checksum size and the offset from the
-          broadcast. */
+       /*
+        * Add on the checksum size and the offset from the
+        * broadcast.
+        */
        smi_msg->data_size += 1;
 
        smi_msg->msgid = msgid;
 }
 
-/* Separate from ipmi_request so that the user does not have to be
-   supplied in certain circumstances (mainly at panic time).  If
-   messages are supplied, they will be freed, even if an error
-   occurs. */
+/*
+ * Separate from ipmi_request so that the user does not have to be
+ * supplied in certain circumstances (mainly at panic time).  If
+ * messages are supplied, they will be freed, even if an error
+ * occurs.
+ */
 static int i_ipmi_request(ipmi_user_t          user,
                          ipmi_smi_t           intf,
                          struct ipmi_addr     *addr,
@@ -1319,19 +1404,18 @@ static int i_ipmi_request(ipmi_user_t          user,
        struct ipmi_smi_handlers *handlers;
 
 
-       if (supplied_recv) {
+       if (supplied_recv)
                recv_msg = supplied_recv;
-       else {
+       else {
                recv_msg = ipmi_alloc_recv_msg();
-               if (recv_msg == NULL) {
+               if (recv_msg == NULL)
                        return -ENOMEM;
-               }
        }
        recv_msg->user_msg_data = user_msg_data;
 
-       if (supplied_smi) {
+       if (supplied_smi)
                smi_msg = (struct ipmi_smi_msg *) supplied_smi;
-       else {
+       else {
                smi_msg = ipmi_alloc_smi_msg();
                if (smi_msg == NULL) {
                        ipmi_free_recv_msg(recv_msg);
@@ -1350,8 +1434,10 @@ static int i_ipmi_request(ipmi_user_t          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. */
+       /*
+        * Store the message to send in the receive message so timeout
+        * responses can get the proper response data.
+        */
        recv_msg->msg = *msg;
 
        if (addr->addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) {
@@ -1365,9 +1451,7 @@ static int i_ipmi_request(ipmi_user_t          user,
 
                smi_addr = (struct ipmi_system_interface_addr *) addr;
                if (smi_addr->lun > 3) {
-                       spin_lock_irqsave(&intf->counter_lock, flags);
-                       intf->sent_invalid_commands++;
-                       spin_unlock_irqrestore(&intf->counter_lock, flags);
+                       ipmi_inc_stat(intf, sent_invalid_commands);
                        rv = -EINVAL;
                        goto out_err;
                }
@@ -1377,13 +1461,12 @@ static int i_ipmi_request(ipmi_user_t          user,
                if ((msg->netfn == IPMI_NETFN_APP_REQUEST)
                    && ((msg->cmd == IPMI_SEND_MSG_CMD)
                        || (msg->cmd == IPMI_GET_MSG_CMD)
-                       || (msg->cmd == IPMI_READ_EVENT_MSG_BUFFER_CMD)))
-               {
-                       /* We don't let the user do these, since we manage
-                          the sequence numbers. */
-                       spin_lock_irqsave(&intf->counter_lock, flags);
-                       intf->sent_invalid_commands++;
-                       spin_unlock_irqrestore(&intf->counter_lock, flags);
+                       || (msg->cmd == IPMI_READ_EVENT_MSG_BUFFER_CMD))) {
+                       /*
+                        * We don't let the user do these, since we manage
+                        * the sequence numbers.
+                        */
+                       ipmi_inc_stat(intf, sent_invalid_commands);
                        rv = -EINVAL;
                        goto out_err;
                }
@@ -1391,14 +1474,12 @@ static int i_ipmi_request(ipmi_user_t          user,
                if (((msg->netfn == IPMI_NETFN_APP_REQUEST)
                      && ((msg->cmd == IPMI_COLD_RESET_CMD)
                          || (msg->cmd == IPMI_WARM_RESET_CMD)))
-                    || (msg->netfn == IPMI_NETFN_FIRMWARE_REQUEST))
-               {
+                    || (msg->netfn == IPMI_NETFN_FIRMWARE_REQUEST)) {
                        spin_lock_irqsave(&intf->maintenance_mode_lock, flags);
                        intf->auto_maintenance_timeout
                                = IPMI_MAINTENANCE_MODE_TIMEOUT;
                        if (!intf->maintenance_mode
-                           && !intf->maintenance_mode_enable)
-                       {
+                           && !intf->maintenance_mode_enable) {
                                intf->maintenance_mode_enable = 1;
                                maintenance_mode_update(intf);
                        }
@@ -1407,9 +1488,7 @@ static int i_ipmi_request(ipmi_user_t          user,
                }
 
                if ((msg->data_len + 2) > IPMI_MAX_MSG_LENGTH) {
-                       spin_lock_irqsave(&intf->counter_lock, flags);
-                       intf->sent_invalid_commands++;
-                       spin_unlock_irqrestore(&intf->counter_lock, flags);
+                       ipmi_inc_stat(intf, sent_invalid_commands);
                        rv = -EMSGSIZE;
                        goto out_err;
                }
@@ -1421,31 +1500,23 @@ static int i_ipmi_request(ipmi_user_t          user,
                if (msg->data_len > 0)
                        memcpy(&(smi_msg->data[2]), msg->data, msg->data_len);
                smi_msg->data_size = msg->data_len + 2;
-               spin_lock_irqsave(&intf->counter_lock, flags);
-               intf->sent_local_commands++;
-               spin_unlock_irqrestore(&intf->counter_lock, flags);
+               ipmi_inc_stat(intf, sent_local_commands);
        } else if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE)
-                  || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
-       {
+                  || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)) {
                struct ipmi_ipmb_addr *ipmb_addr;
                unsigned char         ipmb_seq;
                long                  seqid;
                int                   broadcast = 0;
 
                if (addr->channel >= IPMI_MAX_CHANNELS) {
-                       spin_lock_irqsave(&intf->counter_lock, flags);
-                       intf->sent_invalid_commands++;
-                       spin_unlock_irqrestore(&intf->counter_lock, flags);
+                       ipmi_inc_stat(intf, sent_invalid_commands);
                        rv = -EINVAL;
                        goto out_err;
                }
 
                if (intf->channels[addr->channel].medium
-                   != IPMI_CHANNEL_MEDIUM_IPMB)
-               {
-                       spin_lock_irqsave(&intf->counter_lock, flags);
-                       intf->sent_invalid_commands++;
-                       spin_unlock_irqrestore(&intf->counter_lock, flags);
+                                       != IPMI_CHANNEL_MEDIUM_IPMB) {
+                       ipmi_inc_stat(intf, sent_invalid_commands);
                        rv = -EINVAL;
                        goto out_err;
                }
@@ -1457,9 +1528,11 @@ static int i_ipmi_request(ipmi_user_t          user,
                        retries = 4;
                }
                if (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE) {
-                   /* Broadcasts add a zero at the beginning of the
-                      message, but otherwise is the same as an IPMB
-                      address. */
+                   /*
+                    * Broadcasts add a zero at the beginning of the
+                    * message, but otherwise is the same as an IPMB
+                    * address.
+                    */
                    addr->addr_type = IPMI_IPMB_ADDR_TYPE;
                    broadcast = 1;
                }
@@ -1469,21 +1542,19 @@ static int i_ipmi_request(ipmi_user_t          user,
                if (retry_time_ms == 0)
                    retry_time_ms = 1000;
 
-               /* 9 for the header and 1 for the checksum, plus
-                   possibly one for the broadcast. */
+               /*
+                * 9 for the header and 1 for the checksum, plus
+                * possibly one for the broadcast.
+                */
                if ((msg->data_len + 10 + broadcast) > IPMI_MAX_MSG_LENGTH) {
-                       spin_lock_irqsave(&intf->counter_lock, flags);
-                       intf->sent_invalid_commands++;
-                       spin_unlock_irqrestore(&intf->counter_lock, flags);
+                       ipmi_inc_stat(intf, sent_invalid_commands);
                        rv = -EMSGSIZE;
                        goto out_err;
                }
 
                ipmb_addr = (struct ipmi_ipmb_addr *) addr;
                if (ipmb_addr->lun > 3) {
-                       spin_lock_irqsave(&intf->counter_lock, flags);
-                       intf->sent_invalid_commands++;
-                       spin_unlock_irqrestore(&intf->counter_lock, flags);
+                       ipmi_inc_stat(intf, sent_invalid_commands);
                        rv = -EINVAL;
                        goto out_err;
                }
@@ -1491,29 +1562,31 @@ static int i_ipmi_request(ipmi_user_t          user,
                memcpy(&recv_msg->addr, ipmb_addr, sizeof(*ipmb_addr));
 
                if (recv_msg->msg.netfn & 0x1) {
-                       /* It's a response, so use the user's sequence
-                           from msgid. */
-                       spin_lock_irqsave(&intf->counter_lock, flags);
-                       intf->sent_ipmb_responses++;
-                       spin_unlock_irqrestore(&intf->counter_lock, flags);
+                       /*
+                        * It's a response, so use the user's sequence
+                        * from msgid.
+                        */
+                       ipmi_inc_stat(intf, sent_ipmb_responses);
                        format_ipmb_msg(smi_msg, msg, ipmb_addr, msgid,
                                        msgid, broadcast,
                                        source_address, source_lun);
 
-                       /* Save the receive message so we can use it
-                          to deliver the response. */
+                       /*
+                        * Save the receive message so we can use it
+                        * to deliver the response.
+                        */
                        smi_msg->user_data = recv_msg;
                } else {
                        /* It's a command, so get a sequence for it. */
 
                        spin_lock_irqsave(&(intf->seq_lock), flags);
 
-                       spin_lock(&intf->counter_lock);
-                       intf->sent_ipmb_commands++;
-                       spin_unlock(&intf->counter_lock);
+                       ipmi_inc_stat(intf, sent_ipmb_commands);
 
-                       /* Create a sequence number with a 1 second
-                           timeout and 4 retries. */
+                       /*
+                        * Create a sequence number with a 1 second
+                        * timeout and 4 retries.
+                        */
                        rv = intf_next_seq(intf,
                                           recv_msg,
                                           retry_time_ms,
@@ -1522,34 +1595,42 @@ static int i_ipmi_request(ipmi_user_t          user,
                                           &ipmb_seq,
                                           &seqid);
                        if (rv) {
-                               /* We have used up all the sequence numbers,
-                                  probably, so abort. */
+                               /*
+                                * We have used up all the sequence numbers,
+                                * probably, so abort.
+                                */
                                spin_unlock_irqrestore(&(intf->seq_lock),
                                                       flags);
                                goto out_err;
                        }
 
-                       /* Store the sequence number in the message,
-                           so that when the send message response
-                           comes back we can start the timer. */
+                       /*
+                        * Store the sequence number in the message,
+                        * so that when the send message response
+                        * comes back we can start the timer.
+                        */
                        format_ipmb_msg(smi_msg, msg, ipmb_addr,
                                        STORE_SEQ_IN_MSGID(ipmb_seq, seqid),
                                        ipmb_seq, broadcast,
                                        source_address, source_lun);
 
-                       /* Copy the message into the recv message data, so we
-                          can retransmit it later if necessary. */
+                       /*
+                        * Copy the message into the recv message data, so we
+                        * can retransmit it later if necessary.
+                        */
                        memcpy(recv_msg->msg_data, smi_msg->data,
                               smi_msg->data_size);
                        recv_msg->msg.data = recv_msg->msg_data;
                        recv_msg->msg.data_len = smi_msg->data_size;
 
-                       /* We don't unlock until here, because we need
-                           to copy the completed message into the
-                           recv_msg before we release the lock.
-                           Otherwise, race conditions may bite us.  I
-                           know that's pretty paranoid, but I prefer
-                           to be correct. */
+                       /*
+                        * We don't unlock until here, because we need
+                        * to copy the completed message into the
+                        * recv_msg before we release the lock.
+                        * Otherwise, race conditions may bite us.  I
+                        * know that's pretty paranoid, but I prefer
+                        * to be correct.
+                        */
                        spin_unlock_irqrestore(&(intf->seq_lock), flags);
                }
        } else if (addr->addr_type == IPMI_LAN_ADDR_TYPE) {
@@ -1558,21 +1639,16 @@ static int i_ipmi_request(ipmi_user_t          user,
                long                  seqid;
 
                if (addr->channel >= IPMI_MAX_CHANNELS) {
-                       spin_lock_irqsave(&intf->counter_lock, flags);
-                       intf->sent_invalid_commands++;
-                       spin_unlock_irqrestore(&intf->counter_lock, flags);
+                       ipmi_inc_stat(intf, sent_invalid_commands);
                        rv = -EINVAL;
                        goto out_err;
                }
 
                if ((intf->channels[addr->channel].medium
-                   != IPMI_CHANNEL_MEDIUM_8023LAN)
+                               != IPMI_CHANNEL_MEDIUM_8023LAN)
                    && (intf->channels[addr->channel].medium
-                       != IPMI_CHANNEL_MEDIUM_ASYNC))
-               {
-                       spin_lock_irqsave(&intf->counter_lock, flags);
-                       intf->sent_invalid_commands++;
-                       spin_unlock_irqrestore(&intf->counter_lock, flags);
+                               != IPMI_CHANNEL_MEDIUM_ASYNC)) {
+                       ipmi_inc_stat(intf, sent_invalid_commands);
                        rv = -EINVAL;
                        goto out_err;
                }
@@ -1585,18 +1661,14 @@ static int i_ipmi_request(ipmi_user_t          user,
 
                /* 11 for the header and 1 for the checksum. */
                if ((msg->data_len + 12) > IPMI_MAX_MSG_LENGTH) {
-                       spin_lock_irqsave(&intf->counter_lock, flags);
-                       intf->sent_invalid_commands++;
-                       spin_unlock_irqrestore(&intf->counter_lock, flags);
+                       ipmi_inc_stat(intf, sent_invalid_commands);
                        rv = -EMSGSIZE;
                        goto out_err;
                }
 
                lan_addr = (struct ipmi_lan_addr *) addr;
                if (lan_addr->lun > 3) {
-                       spin_lock_irqsave(&intf->counter_lock, flags);
-                       intf->sent_invalid_commands++;
-                       spin_unlock_irqrestore(&intf->counter_lock, flags);
+                       ipmi_inc_stat(intf, sent_invalid_commands);
                        rv = -EINVAL;
                        goto out_err;
                }
@@ -1604,28 +1676,30 @@ static int i_ipmi_request(ipmi_user_t          user,
                memcpy(&recv_msg->addr, lan_addr, sizeof(*lan_addr));
 
                if (recv_msg->msg.netfn & 0x1) {
-                       /* It's a response, so use the user's sequence
-                           from msgid. */
-                       spin_lock_irqsave(&intf->counter_lock, flags);
-                       intf->sent_lan_responses++;
-                       spin_unlock_irqrestore(&intf->counter_lock, flags);
+                       /*
+                        * It's a response, so use the user's sequence
+                        * from msgid.
+                        */
+                       ipmi_inc_stat(intf, sent_lan_responses);
                        format_lan_msg(smi_msg, msg, lan_addr, msgid,
                                       msgid, source_lun);
 
-                       /* Save the receive message so we can use it
-                          to deliver the response. */
+                       /*
+                        * Save the receive message so we can use it
+                        * to deliver the response.
+                        */
                        smi_msg->user_data = recv_msg;
                } else {
                        /* It's a command, so get a sequence for it. */
 
                        spin_lock_irqsave(&(intf->seq_lock), flags);
 
-                       spin_lock(&intf->counter_lock);
-                       intf->sent_lan_commands++;
-                       spin_unlock(&intf->counter_lock);
+                       ipmi_inc_stat(intf, sent_lan_commands);
 
-                       /* Create a sequence number with a 1 second
-                           timeout and 4 retries. */
+                       /*
+                        * Create a sequence number with a 1 second
+                        * timeout and 4 retries.
+                        */
                        rv = intf_next_seq(intf,
                                           recv_msg,
                                           retry_time_ms,
@@ -1634,40 +1708,46 @@ static int i_ipmi_request(ipmi_user_t          user,
                                           &ipmb_seq,
                                           &seqid);
                        if (rv) {
-                               /* We have used up all the sequence numbers,
-                                  probably, so abort. */
+                               /*
+                                * We have used up all the sequence numbers,
+                                * probably, so abort.
+                                */
                                spin_unlock_irqrestore(&(intf->seq_lock),
                                                       flags);
                                goto out_err;
                        }
 
-                       /* Store the sequence number in the message,
-                           so that when the send message response
-                           comes back we can start the timer. */
+                       /*
+                        * Store the sequence number in the message,
+                        * so that when the send message response
+                        * comes back we can start the timer.
+                        */
                        format_lan_msg(smi_msg, msg, lan_addr,
                                       STORE_SEQ_IN_MSGID(ipmb_seq, seqid),
                                       ipmb_seq, source_lun);
 
-                       /* Copy the message into the recv message data, so we
-                          can retransmit it later if necessary. */
+                       /*
+                        * Copy the message into the recv message data, so we
+                        * can retransmit it later if necessary.
+                        */
                        memcpy(recv_msg->msg_data, smi_msg->data,
                               smi_msg->data_size);
                        recv_msg->msg.data = recv_msg->msg_data;
                        recv_msg->msg.data_len = smi_msg->data_size;
 
-                       /* We don't unlock until here, because we need
-                           to copy the completed message into the
-                           recv_msg before we release the lock.
-                           Otherwise, race conditions may bite us.  I
-                           know that's pretty paranoid, but I prefer
-                           to be correct. */
+                       /*
+                        * We don't unlock until here, because we need
+                        * to copy the completed message into the
+                        * recv_msg before we release the lock.
+                        * Otherwise, race conditions may bite us.  I
+                        * know that's pretty paranoid, but I prefer
+                        * to be correct.
+                        */
                        spin_unlock_irqrestore(&(intf->seq_lock), flags);
                }
        } else {
            /* Unknown address type. */
-               spin_lock_irqsave(&intf->counter_lock, flags);
-               intf->sent_invalid_commands++;
-               spin_unlock_irqrestore(&intf->counter_lock, flags);
+               ipmi_inc_stat(intf, sent_invalid_commands);
                rv = -EINVAL;
                goto out_err;
        }
@@ -1735,6 +1815,7 @@ int ipmi_request_settime(ipmi_user_t      user,
                              retries,
                              retry_time_ms);
 }
+EXPORT_SYMBOL(ipmi_request_settime);
 
 int ipmi_request_supply_msgs(ipmi_user_t          user,
                             struct ipmi_addr     *addr,
@@ -1766,6 +1847,7 @@ int ipmi_request_supply_msgs(ipmi_user_t          user,
                              lun,
                              -1, 0);
 }
+EXPORT_SYMBOL(ipmi_request_supply_msgs);
 
 #ifdef CONFIG_PROC_FS
 static int ipmb_file_read_proc(char *page, char **start, off_t off,
@@ -1790,7 +1872,7 @@ static int version_file_read_proc(char *page, char **start, off_t off,
        char       *out = (char *) page;
        ipmi_smi_t intf = data;
 
-       return sprintf(out, "%d.%d\n",
+       return sprintf(out, "%u.%u\n",
                       ipmi_version_major(&intf->bmc->id),
                       ipmi_version_minor(&intf->bmc->id));
 }
@@ -1801,65 +1883,65 @@ static int stat_file_read_proc(char *page, char **start, off_t off,
        char       *out = (char *) page;
        ipmi_smi_t intf = data;
 
-       out += sprintf(out, "sent_invalid_commands:       %d\n",
-                      intf->sent_invalid_commands);
-       out += sprintf(out, "sent_local_commands:         %d\n",
-                      intf->sent_local_commands);
-       out += sprintf(out, "handled_local_responses:     %d\n",
-                      intf->handled_local_responses);
-       out += sprintf(out, "unhandled_local_responses:   %d\n",
-                      intf->unhandled_local_responses);
-       out += sprintf(out, "sent_ipmb_commands:          %d\n",
-                      intf->sent_ipmb_commands);
-       out += sprintf(out, "sent_ipmb_command_errs:      %d\n",
-                      intf->sent_ipmb_command_errs);
-       out += sprintf(out, "retransmitted_ipmb_commands: %d\n",
-                      intf->retransmitted_ipmb_commands);
-       out += sprintf(out, "timed_out_ipmb_commands:     %d\n",
-                      intf->timed_out_ipmb_commands);
-       out += sprintf(out, "timed_out_ipmb_broadcasts:   %d\n",
-                      intf->timed_out_ipmb_broadcasts);
-       out += sprintf(out, "sent_ipmb_responses:         %d\n",
-                      intf->sent_ipmb_responses);
-       out += sprintf(out, "handled_ipmb_responses:      %d\n",
-                      intf->handled_ipmb_responses);
-       out += sprintf(out, "invalid_ipmb_responses:      %d\n",
-                      intf->invalid_ipmb_responses);
-       out += sprintf(out, "unhandled_ipmb_responses:    %d\n",
-                      intf->unhandled_ipmb_responses);
-       out += sprintf(out, "sent_lan_commands:           %d\n",
-                      intf->sent_lan_commands);
-       out += sprintf(out, "sent_lan_command_errs:       %d\n",
-                      intf->sent_lan_command_errs);
-       out += sprintf(out, "retransmitted_lan_commands:  %d\n",
-                      intf->retransmitted_lan_commands);
-       out += sprintf(out, "timed_out_lan_commands:      %d\n",
-                      intf->timed_out_lan_commands);
-       out += sprintf(out, "sent_lan_responses:          %d\n",
-                      intf->sent_lan_responses);
-       out += sprintf(out, "handled_lan_responses:       %d\n",
-                      intf->handled_lan_responses);
-       out += sprintf(out, "invalid_lan_responses:       %d\n",
-                      intf->invalid_lan_responses);
-       out += sprintf(out, "unhandled_lan_responses:     %d\n",
-                      intf->unhandled_lan_responses);
-       out += sprintf(out, "handled_commands:            %d\n",
-                      intf->handled_commands);
-       out += sprintf(out, "invalid_commands:            %d\n",
-                      intf->invalid_commands);
-       out += sprintf(out, "unhandled_commands:          %d\n",
-                      intf->unhandled_commands);
-       out += sprintf(out, "invalid_events:              %d\n",
-                      intf->invalid_events);
-       out += sprintf(out, "events:                      %d\n",
-                      intf->events);
+       out += sprintf(out, "sent_invalid_commands:       %u\n",
+                      ipmi_get_stat(intf, sent_invalid_commands));
+       out += sprintf(out, "sent_local_commands:         %u\n",
+                      ipmi_get_stat(intf, sent_local_commands));
+       out += sprintf(out, "handled_local_responses:     %u\n",
+                      ipmi_get_stat(intf, handled_local_responses));
+       out += sprintf(out, "unhandled_local_responses:   %u\n",
+                      ipmi_get_stat(intf, unhandled_local_responses));
+       out += sprintf(out, "sent_ipmb_commands:          %u\n",
+                      ipmi_get_stat(intf, sent_ipmb_commands));
+       out += sprintf(out, "sent_ipmb_command_errs:      %u\n",
+                      ipmi_get_stat(intf, sent_ipmb_command_errs));
+       out += sprintf(out, "retransmitted_ipmb_commands: %u\n",
+                      ipmi_get_stat(intf, retransmitted_ipmb_commands));
+       out += sprintf(out, "timed_out_ipmb_commands:     %u\n",
+                      ipmi_get_stat(intf, timed_out_ipmb_commands));
+       out += sprintf(out, "timed_out_ipmb_broadcasts:   %u\n",
+                      ipmi_get_stat(intf, timed_out_ipmb_broadcasts));
+       out += sprintf(out, "sent_ipmb_responses:         %u\n",
+                      ipmi_get_stat(intf, sent_ipmb_responses));
+       out += sprintf(out, "handled_ipmb_responses:      %u\n",
+                      ipmi_get_stat(intf, handled_ipmb_responses));
+       out += sprintf(out, "invalid_ipmb_responses:      %u\n",
+                      ipmi_get_stat(intf, invalid_ipmb_responses));
+       out += sprintf(out, "unhandled_ipmb_responses:    %u\n",
+                      ipmi_get_stat(intf, unhandled_ipmb_responses));
+       out += sprintf(out, "sent_lan_commands:           %u\n",
+                      ipmi_get_stat(intf, sent_lan_commands));
+       out += sprintf(out, "sent_lan_command_errs:       %u\n",
+                      ipmi_get_stat(intf, sent_lan_command_errs));
+       out += sprintf(out, "retransmitted_lan_commands:  %u\n",
+                      ipmi_get_stat(intf, retransmitted_lan_commands));
+       out += sprintf(out, "timed_out_lan_commands:      %u\n",
+                      ipmi_get_stat(intf, timed_out_lan_commands));
+       out += sprintf(out, "sent_lan_responses:          %u\n",
+                      ipmi_get_stat(intf, sent_lan_responses));
+       out += sprintf(out, "handled_lan_responses:       %u\n",
+                      ipmi_get_stat(intf, handled_lan_responses));
+       out += sprintf(out, "invalid_lan_responses:       %u\n",
+                      ipmi_get_stat(intf, invalid_lan_responses));
+       out += sprintf(out, "unhandled_lan_responses:     %u\n",
+                      ipmi_get_stat(intf, unhandled_lan_responses));
+       out += sprintf(out, "handled_commands:            %u\n",
+                      ipmi_get_stat(intf, handled_commands));
+       out += sprintf(out, "invalid_commands:            %u\n",
+                      ipmi_get_stat(intf, invalid_commands));
+       out += sprintf(out, "unhandled_commands:          %u\n",
+                      ipmi_get_stat(intf, unhandled_commands));
+       out += sprintf(out, "invalid_events:              %u\n",
+                      ipmi_get_stat(intf, invalid_events));
+       out += sprintf(out, "events:                      %u\n",
+                      ipmi_get_stat(intf, events));
 
        return (out - ((char *) page));
 }
 #endif /* CONFIG_PROC_FS */
 
 int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
-                           read_proc_t *read_proc, write_proc_t *write_proc,
+                           read_proc_t *read_proc,
                            void *data, struct module *owner)
 {
        int                    rv = 0;
@@ -1886,7 +1968,6 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
        } else {
                file->data = data;
                file->read_proc = read_proc;
-               file->write_proc = write_proc;
                file->owner = owner;
 
                mutex_lock(&smi->proc_entry_lock);
@@ -1899,6 +1980,7 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
 
        return rv;
 }
+EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
 
 static int add_proc_entries(ipmi_smi_t smi, int num)
 {
@@ -1909,23 +1991,22 @@ static int add_proc_entries(ipmi_smi_t smi, int num)
        smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root);
        if (!smi->proc_dir)
                rv = -ENOMEM;
-       else {
+       else
                smi->proc_dir->owner = THIS_MODULE;
-       }
 
        if (rv == 0)
                rv = ipmi_smi_add_proc_entry(smi, "stats",
-                                            stat_file_read_proc, NULL,
+                                            stat_file_read_proc,
                                             smi, THIS_MODULE);
 
        if (rv == 0)
                rv = ipmi_smi_add_proc_entry(smi, "ipmb",
-                                            ipmb_file_read_proc, NULL,
+                                            ipmb_file_read_proc,
                                             smi, THIS_MODULE);
 
        if (rv == 0)
                rv = ipmi_smi_add_proc_entry(smi, "version",
-                                            version_file_read_proc, NULL,
+                                            version_file_read_proc,
                                             smi, THIS_MODULE);
 #endif /* CONFIG_PROC_FS */
 
@@ -2210,37 +2291,47 @@ static int create_files(struct bmc_device *bmc)
 
        err = device_create_file(&bmc->dev->dev,
                           &bmc->device_id_attr);
-       if (err) goto out;
+       if (err)
+               goto out;
        err = device_create_file(&bmc->dev->dev,
                           &bmc->provides_dev_sdrs_attr);
-       if (err) goto out_devid;
+       if (err)
+               goto out_devid;
        err = device_create_file(&bmc->dev->dev,
                           &bmc->revision_attr);
-       if (err) goto out_sdrs;
+       if (err)
+               goto out_sdrs;
        err = device_create_file(&bmc->dev->dev,
                           &bmc->firmware_rev_attr);
-       if (err) goto out_rev;
+       if (err)
+               goto out_rev;
        err = device_create_file(&bmc->dev->dev,
                           &bmc->version_attr);
-       if (err) goto out_firm;
+       if (err)
+               goto out_firm;
        err = device_create_file(&bmc->dev->dev,
                           &bmc->add_dev_support_attr);
-       if (err) goto out_version;
+       if (err)
+               goto out_version;
        err = device_create_file(&bmc->dev->dev,
                           &bmc->manufacturer_id_attr);
-       if (err) goto out_add_dev;
+       if (err)
+               goto out_add_dev;
        err = device_create_file(&bmc->dev->dev,
                           &bmc->product_id_attr);
-       if (err) goto out_manu;
+       if (err)
+               goto out_manu;
        if (bmc->id.aux_firmware_revision_set) {
                err = device_create_file(&bmc->dev->dev,
                                   &bmc->aux_firmware_rev_attr);
-               if (err) goto out_prod_id;
+               if (err)
+                       goto out_prod_id;
        }
        if (bmc->guid_set) {
                err = device_create_file(&bmc->dev->dev,
                                   &bmc->guid_attr);
-               if (err) goto out_aux_firm;
+               if (err)
+                       goto out_aux_firm;
        }
 
        return 0;
@@ -2368,8 +2459,10 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum,
                               "ipmi_msghandler:"
                               " Unable to register bmc device: %d\n",
                               rv);
-                       /* Don't go to out_err, you can only do that if
-                          the device is registered already. */
+                       /*
+                        * Don't go to out_err, you can only do that if
+                        * the device is registered already.
+                        */
                        return rv;
                }
 
@@ -2560,17 +2653,18 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
 
        if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
            && (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE)
-           && (msg->msg.cmd == IPMI_GET_CHANNEL_INFO_CMD))
-       {
+           && (msg->msg.cmd == IPMI_GET_CHANNEL_INFO_CMD)) {
                /* It's the one we want */
                if (msg->msg.data[0] != 0) {
                        /* Got an error from the channel, just go on. */
 
                        if (msg->msg.data[0] == IPMI_INVALID_COMMAND_ERR) {
-                               /* If the MC does not support this
-                                  command, that is legal.  We just
-                                  assume it has one IPMB at channel
-                                  zero. */
+                               /*
+                                * If the MC does not support this
+                                * command, that is legal.  We just
+                                * assume it has one IPMB at channel
+                                * zero.
+                                */
                                intf->channels[0].medium
                                        = IPMI_CHANNEL_MEDIUM_IPMB;
                                intf->channels[0].protocol
@@ -2591,7 +2685,7 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
                intf->channels[chan].medium = msg->msg.data[2] & 0x7f;
                intf->channels[chan].protocol = msg->msg.data[3] & 0x1f;
 
      next_channel:
+ next_channel:
                intf->curr_channel++;
                if (intf->curr_channel >= IPMI_MAX_CHANNELS)
                        wake_up(&intf->waitq);
@@ -2619,6 +2713,7 @@ void ipmi_poll_interface(ipmi_user_t user)
        if (intf->handlers->poll)
                intf->handlers->poll(intf->send_info);
 }
+EXPORT_SYMBOL(ipmi_poll_interface);
 
 int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
                      void                     *send_info,
@@ -2633,14 +2728,18 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
        ipmi_smi_t       tintf;
        struct list_head *link;
 
-       /* Make sure the driver is actually initialized, this handles
-          problems with initialization order. */
+       /*
+        * Make sure the driver is actually initialized, this handles
+        * problems with initialization order.
+        */
        if (!initialized) {
                rv = ipmi_init_msghandler();
                if (rv)
                        return rv;
-               /* The init code doesn't return an error if it was turned
-                  off, but it won't initialize.  Check that. */
+               /*
+                * The init code doesn't return an error if it was turned
+                * off, but it won't initialize.  Check that.
+                */
                if (!initialized)
                        return -ENODEV;
        }
@@ -2688,8 +2787,9 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
        spin_lock_init(&intf->maintenance_mode_lock);
        INIT_LIST_HEAD(&intf->cmd_rcvrs);
        init_waitqueue_head(&intf->waitq);
+       for (i = 0; i < IPMI_NUM_STATS; i++)
+               atomic_set(&intf->stats[i], 0);
 
-       spin_lock_init(&intf->counter_lock);
        intf->proc_dir = NULL;
 
        mutex_lock(&smi_watchers_mutex);
@@ -2717,11 +2817,12 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
        get_guid(intf);
 
        if ((intf->ipmi_version_major > 1)
-           || ((intf->ipmi_version_major == 1)
-               && (intf->ipmi_version_minor >= 5)))
-       {
-               /* Start scanning the channels to see what is
-                  available. */
+                       || ((intf->ipmi_version_major == 1)
+                           && (intf->ipmi_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);
@@ -2769,6 +2870,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
 
        return rv;
 }
+EXPORT_SYMBOL(ipmi_register_smi);
 
 static void cleanup_smi_msgs(ipmi_smi_t intf)
 {
@@ -2803,8 +2905,10 @@ int ipmi_unregister_smi(ipmi_smi_t intf)
 
        remove_proc_entries(intf);
 
-       /* Call all the watcher interfaces to tell them that
-          an interface is gone. */
+       /*
+        * Call all the watcher interfaces to tell them that
+        * an interface is gone.
+        */
        list_for_each_entry(w, &smi_watchers, link)
                w->smi_gone(intf_num);
        mutex_unlock(&smi_watchers_mutex);
@@ -2812,22 +2916,21 @@ int ipmi_unregister_smi(ipmi_smi_t intf)
        kref_put(&intf->refcount, intf_free);
        return 0;
 }
+EXPORT_SYMBOL(ipmi_unregister_smi);
 
 static int handle_ipmb_get_msg_rsp(ipmi_smi_t          intf,
                                   struct ipmi_smi_msg *msg)
 {
        struct ipmi_ipmb_addr ipmb_addr;
        struct ipmi_recv_msg  *recv_msg;
-       unsigned long         flags;
 
-       
-       /* This is 11, not 10, because the response must contain a
-        * completion code. */
+       /*
+        * This is 11, not 10, because the response must contain a
+        * completion code.
+        */
        if (msg->rsp_size < 11) {
                /* Message not big enough, just ignore it. */
-               spin_lock_irqsave(&intf->counter_lock, flags);
-               intf->invalid_ipmb_responses++;
-               spin_unlock_irqrestore(&intf->counter_lock, flags);
+               ipmi_inc_stat(intf, invalid_ipmb_responses);
                return 0;
        }
 
@@ -2841,37 +2944,38 @@ static int handle_ipmb_get_msg_rsp(ipmi_smi_t          intf,
        ipmb_addr.channel = msg->rsp[3] & 0x0f;
        ipmb_addr.lun = msg->rsp[7] & 3;
 
-       /* It's a response from a remote entity.  Look up the sequence
-          number and handle the response. */
+       /*
+        * It's a response from a remote entity.  Look up the sequence
+        * number and handle the response.
+        */
        if (intf_find_seq(intf,
                          msg->rsp[7] >> 2,
                          msg->rsp[3] & 0x0f,
                          msg->rsp[8],
                          (msg->rsp[4] >> 2) & (~1),
                          (struct ipmi_addr *) &(ipmb_addr),
-                         &recv_msg))
-       {
-               /* We were unable to find the sequence number,
-                  so just nuke the message. */
-               spin_lock_irqsave(&intf->counter_lock, flags);
-               intf->unhandled_ipmb_responses++;
-               spin_unlock_irqrestore(&intf->counter_lock, flags);
+                         &recv_msg)) {
+               /*
+                * We were unable to find the sequence number,
+                * so just nuke the message.
+                */
+               ipmi_inc_stat(intf, unhandled_ipmb_responses);
                return 0;
        }
 
        memcpy(recv_msg->msg_data,
               &(msg->rsp[9]),
               msg->rsp_size - 9);
-       /* THe other fields matched, so no need to set them, except
-           for netfn, which needs to be the response that was
-           returned, not the request value. */
+       /*
+        * The other fields matched, so no need to set them, except
+        * for netfn, which needs to be the response that was
+        * returned, not the request value.
+        */
        recv_msg->msg.netfn = msg->rsp[4] >> 2;
        recv_msg->msg.data = recv_msg->msg_data;
        recv_msg->msg.data_len = msg->rsp_size - 10;
        recv_msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
-       spin_lock_irqsave(&intf->counter_lock, flags);
-       intf->handled_ipmb_responses++;
-       spin_unlock_irqrestore(&intf->counter_lock, flags);
+       ipmi_inc_stat(intf, handled_ipmb_responses);
        deliver_response(recv_msg);
 
        return 0;
@@ -2888,14 +2992,11 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t          intf,
        ipmi_user_t              user = NULL;
        struct ipmi_ipmb_addr    *ipmb_addr;
        struct ipmi_recv_msg     *recv_msg;
-       unsigned long            flags;
        struct ipmi_smi_handlers *handlers;
 
        if (msg->rsp_size < 10) {
                /* Message not big enough, just ignore it. */
-               spin_lock_irqsave(&intf->counter_lock, flags);
-               intf->invalid_commands++;
-               spin_unlock_irqrestore(&intf->counter_lock, flags);
+               ipmi_inc_stat(intf, invalid_commands);
                return 0;
        }
 
@@ -2919,19 +3020,17 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t          intf,
 
        if (user == NULL) {
                /* We didn't find a user, deliver an error response. */
-               spin_lock_irqsave(&intf->counter_lock, flags);
-               intf->unhandled_commands++;
-               spin_unlock_irqrestore(&intf->counter_lock, flags);
+               ipmi_inc_stat(intf, unhandled_commands);
 
                msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
                msg->data[1] = IPMI_SEND_MSG_CMD;
                msg->data[2] = msg->rsp[3];
                msg->data[3] = msg->rsp[6];
-                msg->data[4] = ((netfn + 1) << 2) | (msg->rsp[7] & 0x3);
+               msg->data[4] = ((netfn + 1) << 2) | (msg->rsp[7] & 0x3);
                msg->data[5] = ipmb_checksum(&(msg->data[3]), 2);
                msg->data[6] = intf->channels[msg->rsp[3] & 0xf].address;
-                /* rqseq/lun */
-                msg->data[7] = (msg->rsp[7] & 0xfc) | (msg->rsp[4] & 0x3);
+               /* rqseq/lun */
+               msg->data[7] = (msg->rsp[7] & 0xfc) | (msg->rsp[4] & 0x3);
                msg->data[8] = msg->rsp[8]; /* cmd */
                msg->data[9] = IPMI_INVALID_CMD_COMPLETION_CODE;
                msg->data[10] = ipmb_checksum(&(msg->data[6]), 4);
@@ -2950,23 +3049,25 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t          intf,
                handlers = intf->handlers;
                if (handlers) {
                        handlers->sender(intf->send_info, msg, 0);
-                       /* We used the message, so return the value
-                          that causes it to not be freed or
-                          queued. */
+                       /*
+                        * We used the message, so return the value
+                        * that causes it to not be freed or
+                        * queued.
+                        */
                        rv = -1;
                }
                rcu_read_unlock();
        } else {
                /* Deliver the message to the user. */
-               spin_lock_irqsave(&intf->counter_lock, flags);
-               intf->handled_commands++;
-               spin_unlock_irqrestore(&intf->counter_lock, flags);
+               ipmi_inc_stat(intf, handled_commands);
 
                recv_msg = ipmi_alloc_recv_msg();
                if (!recv_msg) {
-                       /* We couldn't allocate memory for the
-                           message, so requeue it for handling
-                           later. */
+                       /*
+                        * We couldn't allocate memory for the
+                        * message, so requeue it for handling
+                        * later.
+                        */
                        rv = 1;
                        kref_put(&user->refcount, free_user);
                } else {
@@ -2977,8 +3078,10 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t          intf,
                        ipmb_addr->lun = msg->rsp[7] & 3;
                        ipmb_addr->channel = msg->rsp[3] & 0xf;
 
-                       /* Extract the rest of the message information
-                          from the IPMB header.*/
+                       /*
+                        * Extract the rest of the message information
+                        * from the IPMB header.
+                        */
                        recv_msg->user = user;
                        recv_msg->recv_type = IPMI_CMD_RECV_TYPE;
                        recv_msg->msgid = msg->rsp[7] >> 2;
@@ -2986,8 +3089,10 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t          intf,
                        recv_msg->msg.cmd = msg->rsp[8];
                        recv_msg->msg.data = recv_msg->msg_data;
 
-                       /* We chop off 10, not 9 bytes because the checksum
-                          at the end also needs to be removed. */
+                       /*
+                        * We chop off 10, not 9 bytes because the checksum
+                        * at the end also needs to be removed.
+                        */
                        recv_msg->msg.data_len = msg->rsp_size - 10;
                        memcpy(recv_msg->msg_data,
                               &(msg->rsp[9]),
@@ -3004,16 +3109,15 @@ static int handle_lan_get_msg_rsp(ipmi_smi_t          intf,
 {
        struct ipmi_lan_addr  lan_addr;
        struct ipmi_recv_msg  *recv_msg;
-       unsigned long         flags;
 
 
-       /* This is 13, not 12, because the response must contain a
-        * completion code. */
+       /*
+        * This is 13, not 12, because the response must contain a
+        * completion code.
+        */
        if (msg->rsp_size < 13) {
                /* Message not big enough, just ignore it. */
-               spin_lock_irqsave(&intf->counter_lock, flags);
-               intf->invalid_lan_responses++;
-               spin_unlock_irqrestore(&intf->counter_lock, flags);
+               ipmi_inc_stat(intf, invalid_lan_responses);
                return 0;
        }
 
@@ -3030,37 +3134,38 @@ static int handle_lan_get_msg_rsp(ipmi_smi_t          intf,
        lan_addr.privilege = msg->rsp[3] >> 4;
        lan_addr.lun = msg->rsp[9] & 3;
 
-       /* It's a response from a remote entity.  Look up the sequence
-          number and handle the response. */
+       /*
+        * It's a response from a remote entity.  Look up the sequence
+        * number and handle the response.
+        */
        if (intf_find_seq(intf,
                          msg->rsp[9] >> 2,
                          msg->rsp[3] & 0x0f,
                          msg->rsp[10],
                          (msg->rsp[6] >> 2) & (~1),
                          (struct ipmi_addr *) &(lan_addr),
-                         &recv_msg))
-       {
-               /* We were unable to find the sequence number,
-                  so just nuke the message. */
-               spin_lock_irqsave(&intf->counter_lock, flags);
-               intf->unhandled_lan_responses++;
-               spin_unlock_irqrestore(&intf->counter_lock, flags);
+                         &recv_msg)) {
+               /*
+                * We were unable to find the sequence number,
+                * so just nuke the message.
+                */
+               ipmi_inc_stat(intf, unhandled_lan_responses);
                return 0;
        }
 
        memcpy(recv_msg->msg_data,
               &(msg->rsp[11]),
               msg->rsp_size - 11);
-       /* The other fields matched, so no need to set them, except
-           for netfn, which needs to be the response that was
-           returned, not the request value. */
+       /*
+        * The other fields matched, so no need to set them, except
+        * for netfn, which needs to be the response that was
+        * returned, not the request value.
+        */
        recv_msg->msg.netfn = msg->rsp[6] >> 2;
        recv_msg->msg.data = recv_msg->msg_data;
        recv_msg->msg.data_len = msg->rsp_size - 12;
        recv_msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
-       spin_lock_irqsave(&intf->counter_lock, flags);
-       intf->handled_lan_responses++;
-       spin_unlock_irqrestore(&intf->counter_lock, flags);
+       ipmi_inc_stat(intf, handled_lan_responses);
        deliver_response(recv_msg);
 
        return 0;
@@ -3077,13 +3182,10 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t          intf,
        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. */
-               spin_lock_irqsave(&intf->counter_lock, flags);
-               intf->invalid_commands++;
-               spin_unlock_irqrestore(&intf->counter_lock, flags);
+               ipmi_inc_stat(intf, invalid_commands);
                return 0;
        }
 
@@ -3107,23 +3209,23 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t          intf,
 
        if (user == NULL) {
                /* 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);
+               ipmi_inc_stat(intf, unhandled_commands);
 
-               rv = 0; /* Don't do anything with these messages, just
-                          allow them to be freed. */
+               /*
+                * Don't do anything with these messages, just allow
+                * them to be freed.
+                */
+               rv = 0;
        } else {
                /* Deliver the message to the user. */
-               spin_lock_irqsave(&intf->counter_lock, flags);
-               intf->handled_commands++;
-               spin_unlock_irqrestore(&intf->counter_lock, flags);
+               ipmi_inc_stat(intf, handled_commands);
 
                recv_msg = ipmi_alloc_recv_msg();
                if (!recv_msg) {
-                       /* We couldn't allocate memory for the
-                           message, so requeue it for handling
-                           later. */
+                       /*
+                        * We couldn't allocate memory for the
+                        * message, so requeue it for handling later.
+                        */
                        rv = 1;
                        kref_put(&user->refcount, free_user);
                } else {
@@ -3137,8 +3239,10 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t          intf,
                        lan_addr->channel = msg->rsp[3] & 0xf;
                        lan_addr->privilege = msg->rsp[3] >> 4;
 
-                       /* Extract the rest of the message information
-                          from the IPMB header.*/
+                       /*
+                        * Extract the rest of the message information
+                        * from the IPMB header.
+                        */
                        recv_msg->user = user;
                        recv_msg->recv_type = IPMI_CMD_RECV_TYPE;
                        recv_msg->msgid = msg->rsp[9] >> 2;
@@ -3146,8 +3250,10 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t          intf,
                        recv_msg->msg.cmd = msg->rsp[10];
                        recv_msg->msg.data = recv_msg->msg_data;
 
-                       /* We chop off 12, not 11 bytes because the checksum
-                          at the end also needs to be removed. */
+                       /*
+                        * We chop off 12, not 11 bytes because the checksum
+                        * at the end also needs to be removed.
+                        */
                        recv_msg->msg.data_len = msg->rsp_size - 12;
                        memcpy(recv_msg->msg_data,
                               &(msg->rsp[11]),
@@ -3163,7 +3269,7 @@ static void copy_event_into_recv_msg(struct ipmi_recv_msg *recv_msg,
                                     struct ipmi_smi_msg  *msg)
 {
        struct ipmi_system_interface_addr *smi_addr;
-       
+
        recv_msg->msgid = 0;
        smi_addr = (struct ipmi_system_interface_addr *) &(recv_msg->addr);
        smi_addr->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
@@ -3189,9 +3295,7 @@ static int handle_read_event_rsp(ipmi_smi_t          intf,
 
        if (msg->rsp_size < 19) {
                /* Message is too small to be an IPMB event. */
-               spin_lock_irqsave(&intf->counter_lock, flags);
-               intf->invalid_events++;
-               spin_unlock_irqrestore(&intf->counter_lock, flags);
+               ipmi_inc_stat(intf, invalid_events);
                return 0;
        }
 
@@ -3204,12 +3308,12 @@ static int handle_read_event_rsp(ipmi_smi_t          intf,
 
        spin_lock_irqsave(&intf->events_lock, flags);
 
-       spin_lock(&intf->counter_lock);
-       intf->events++;
-       spin_unlock(&intf->counter_lock);
+       ipmi_inc_stat(intf, events);
 
-       /* Allocate and fill in one message for every user that is getting
-          events. */
+       /*
+        * Allocate and fill in one message for every user that is
+        * getting events.
+        */
        rcu_read_lock();
        list_for_each_entry_rcu(user, &intf->users, link) {
                if (!user->gets_events)
@@ -3223,9 +3327,11 @@ static int handle_read_event_rsp(ipmi_smi_t          intf,
                                list_del(&recv_msg->link);
                                ipmi_free_recv_msg(recv_msg);
                        }
-                       /* We couldn't allocate memory for the
-                           message, so requeue it for handling
-                           later. */
+                       /*
+                        * We couldn't allocate memory for the
+                        * message, so requeue it for handling
+                        * later.
+                        */
                        rv = 1;
                        goto out;
                }
@@ -3246,13 +3352,17 @@ static int handle_read_event_rsp(ipmi_smi_t          intf,
                        deliver_response(recv_msg);
                }
        } else if (intf->waiting_events_count < MAX_EVENTS_IN_QUEUE) {
-               /* No one to receive the message, put it in queue if there's
-                  not already too many things in the queue. */
+               /*
+                * No one to receive the message, put it in queue if there's
+                * not already too many things in the queue.
+                */
                recv_msg = ipmi_alloc_recv_msg();
                if (!recv_msg) {
-                       /* We couldn't allocate memory for the
-                           message, so requeue it for handling
-                           later. */
+                       /*
+                        * We couldn't allocate memory for the
+                        * message, so requeue it for handling
+                        * later.
+                        */
                        rv = 1;
                        goto out;
                }
@@ -3260,11 +3370,14 @@ static int handle_read_event_rsp(ipmi_smi_t          intf,
                copy_event_into_recv_msg(recv_msg, msg);
                list_add_tail(&(recv_msg->link), &(intf->waiting_events));
                intf->waiting_events_count++;
-       } else {
-               /* There's too many things in the queue, discard this
-                  message. */
-               printk(KERN_WARNING PFX "Event queue full, discarding an"
-                      " incoming event\n");
+       } else if (!intf->event_msg_printed) {
+               /*
+                * There's too many things in the queue, discard this
+                * message.
+                */
+               printk(KERN_WARNING PFX "Event queue full, discarding"
+                      " incoming events\n");
+               intf->event_msg_printed = 1;
        }
 
  out:
@@ -3277,16 +3390,15 @@ static int handle_bmc_rsp(ipmi_smi_t          intf,
                          struct ipmi_smi_msg *msg)
 {
        struct ipmi_recv_msg *recv_msg;
-       unsigned long        flags;
        struct ipmi_user     *user;
 
        recv_msg = (struct ipmi_recv_msg *) msg->user_data;
-       if (recv_msg == NULL)
-       {
-               printk(KERN_WARNING"IPMI message received with no owner. This\n"
-                       "could be because of a malformed message, or\n"
-                       "because of a hardware error.  Contact your\n"
-                       "hardware vender for assistance\n");
+       if (recv_msg == NULL) {
+               printk(KERN_WARNING
+                      "IPMI message received with no owner. This\n"
+                      "could be because of a malformed message, or\n"
+                      "because of a hardware error.  Contact your\n"
+                      "hardware vender for assistance\n");
                return 0;
        }
 
@@ -3294,16 +3406,12 @@ static int handle_bmc_rsp(ipmi_smi_t          intf,
        /* Make sure the user still exists. */
        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++;
-               spin_unlock_irqrestore(&intf->counter_lock, flags);
+               ipmi_inc_stat(intf, unhandled_local_responses);
                ipmi_free_recv_msg(recv_msg);
        } else {
                struct ipmi_system_interface_addr *smi_addr;
 
-               spin_lock_irqsave(&intf->counter_lock, flags);
-               intf->handled_local_responses++;
-               spin_unlock_irqrestore(&intf->counter_lock, flags);
+               ipmi_inc_stat(intf, handled_local_responses);
                recv_msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
                recv_msg->msgid = msg->msgid;
                smi_addr = ((struct ipmi_system_interface_addr *)
@@ -3324,9 +3432,11 @@ static int handle_bmc_rsp(ipmi_smi_t          intf,
        return 0;
 }
 
-/* Handle a new message.  Return 1 if the message should be requeued,
-   0 if the message should be freed, or -1 if the message should not
-   be freed or requeued. */
+/*
+ * Handle a new message.  Return 1 if the message should be requeued,
+ * 0 if the message should be freed, or -1 if the message should not
+ * be freed or requeued.
+ */
 static int handle_new_recv_msg(ipmi_smi_t          intf,
                               struct ipmi_smi_msg *msg)
 {
@@ -3351,10 +3461,12 @@ static int handle_new_recv_msg(ipmi_smi_t          intf,
                msg->rsp[1] = msg->data[1];
                msg->rsp[2] = IPMI_ERR_UNSPECIFIED;
                msg->rsp_size = 3;
-       } else if (((msg->rsp[0] >> 2) != ((msg->data[0] >> 2) | 1))/* Netfn */
-                  || (msg->rsp[1] != msg->data[1]))              /* Command */
-       {
-               /* The response is not even marginally correct. */
+       } else if (((msg->rsp[0] >> 2) != ((msg->data[0] >> 2) | 1))
+                  || (msg->rsp[1] != msg->data[1])) {
+               /*
+                * The NetFN and Command in the response is not even
+                * marginally correct.
+                */
                printk(KERN_WARNING PFX "BMC returned incorrect response,"
                       " expected netfn %x cmd %x, got netfn %x cmd %x\n",
                       (msg->data[0] >> 2) | 1, msg->data[1],
@@ -3369,10 +3481,11 @@ static int handle_new_recv_msg(ipmi_smi_t          intf,
 
        if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2))
            && (msg->rsp[1] == IPMI_SEND_MSG_CMD)
-           && (msg->user_data != NULL))
-       {
-               /* It's a response to a response we sent.  For this we
-                  deliver a send message response to the user. */
+           && (msg->user_data != NULL)) {
+               /*
+                * 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;
 
                requeue = 0;
@@ -3398,8 +3511,7 @@ static int handle_new_recv_msg(ipmi_smi_t          intf,
                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))
-       {
+                  && (msg->rsp[1] == IPMI_GET_MSG_CMD)) {
                /* It's from the receive queue. */
                chan = msg->rsp[3] & 0xf;
                if (chan >= IPMI_MAX_CHANNELS) {
@@ -3411,12 +3523,16 @@ static int handle_new_recv_msg(ipmi_smi_t          intf,
                switch (intf->channels[chan].medium) {
                case IPMI_CHANNEL_MEDIUM_IPMB:
                        if (msg->rsp[4] & 0x04) {
-                               /* It's a response, so find the
-                                  requesting message and send it up. */
+                               /*
+                                * It's a response, so find the
+                                * requesting message and send it up.
+                                */
                                requeue = handle_ipmb_get_msg_rsp(intf, msg);
                        } else {
-                               /* It's a command to the SMS from some other
-                                  entity.  Handle that. */
+                               /*
+                                * It's a command to the SMS from some other
+                                * entity.  Handle that.
+                                */
                                requeue = handle_ipmb_get_msg_cmd(intf, msg);
                        }
                        break;
@@ -3424,25 +3540,30 @@ static int handle_new_recv_msg(ipmi_smi_t          intf,
                case IPMI_CHANNEL_MEDIUM_8023LAN:
                case IPMI_CHANNEL_MEDIUM_ASYNC:
                        if (msg->rsp[6] & 0x04) {
-                               /* It's a response, so find the
-                                  requesting message and send it up. */
+                               /*
+                                * It's a response, so find the
+                                * requesting message and send it up.
+                                */
                                requeue = handle_lan_get_msg_rsp(intf, msg);
                        } else {
-                               /* It's a command to the SMS from some other
-                                  entity.  Handle that. */
+                               /*
+                                * It's a command to the SMS from some other
+                                * entity.  Handle that.
+                                */
                                requeue = handle_lan_get_msg_cmd(intf, msg);
                        }
                        break;
 
                default:
-                       /* We don't handle the channel type, so just
-                        * free the message. */
+                       /*
+                        * We don't handle the channel type, so just
+                        * free the message.
+                        */
                        requeue = 0;
                }
 
        } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2))
-                  && (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD))
-       {
+                  && (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD)) {
                /* It's an asyncronous event. */
                requeue = handle_read_event_rsp(intf, msg);
        } else {
@@ -3458,71 +3579,82 @@ static int handle_new_recv_msg(ipmi_smi_t          intf,
 void ipmi_smi_msg_received(ipmi_smi_t          intf,
                           struct ipmi_smi_msg *msg)
 {
-       unsigned long flags;
+       unsigned long flags = 0; /* keep us warning-free. */
        int           rv;
+       int           run_to_completion;
 
 
        if ((msg->data_size >= 2)
            && (msg->data[0] == (IPMI_NETFN_APP_REQUEST << 2))
            && (msg->data[1] == IPMI_SEND_MSG_CMD)
-           && (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
-                   response sends just go through. */
-
-               /* Check for errors, if we get certain errors (ones
-                   that mean basically we can try again later), we
-                   ignore them and start the timer.  Otherwise we
-                   report the error immediately. */
+           && (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
+                * response sends just go through.
+                */
+
+               /*
+                * Check for errors, if we get certain errors (ones
+                * that mean basically we can try again later), we
+                * ignore them and start the timer.  Otherwise we
+                * report the error immediately.
+                */
                if ((msg->rsp_size >= 3) && (msg->rsp[2] != 0)
                    && (msg->rsp[2] != IPMI_NODE_BUSY_ERR)
                    && (msg->rsp[2] != IPMI_LOST_ARBITRATION_ERR)
                    && (msg->rsp[2] != IPMI_BUS_ERR)
-                   && (msg->rsp[2] != IPMI_NAK_ON_WRITE_ERR))
-               {
+                   && (msg->rsp[2] != IPMI_NAK_ON_WRITE_ERR)) {
                        int chan = msg->rsp[3] & 0xf;
 
                        /* Got an error sending the message, handle it. */
-                       spin_lock_irqsave(&intf->counter_lock, flags);
                        if (chan >= IPMI_MAX_CHANNELS)
                                ; /* This shouldn't happen */
                        else if ((intf->channels[chan].medium
                                  == IPMI_CHANNEL_MEDIUM_8023LAN)
                                 || (intf->channels[chan].medium
                                     == IPMI_CHANNEL_MEDIUM_ASYNC))
-                               intf->sent_lan_command_errs++;
+                               ipmi_inc_stat(intf, sent_lan_command_errs);
                        else
-                               intf->sent_ipmb_command_errs++;
-                       spin_unlock_irqrestore(&intf->counter_lock, flags);
+                               ipmi_inc_stat(intf, sent_ipmb_command_errs);
                        intf_err_seq(intf, msg->msgid, msg->rsp[2]);
-               } else {
+               } else
                        /* The message was sent, start the timer. */
                        intf_start_seq_timer(intf, msg->msgid);
-               }
 
                ipmi_free_smi_msg(msg);
                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);
+       /*
+        * To preserve message order, if the list is not empty, we
+        * tack this message onto the end of the list.
+        */
+       run_to_completion = intf->run_to_completion;
+       if (!run_to_completion)
+               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);
+               if (!run_to_completion)
+                       spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
                goto out;
        }
-       spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
-               
+       if (!run_to_completion)
+               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);
+               /*
+                * Could not handle the message now, just add it to a
+                * list to handle later.
+                */
+               run_to_completion = intf->run_to_completion;
+               if (!run_to_completion)
+                       spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
                list_add_tail(&msg->link, &intf->waiting_msgs);
-               spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
+               if (!run_to_completion)
+                       spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
        } else if (rv == 0) {
                ipmi_free_smi_msg(msg);
        }
@@ -3530,6 +3662,7 @@ void ipmi_smi_msg_received(ipmi_smi_t          intf,
  out:
        return;
 }
+EXPORT_SYMBOL(ipmi_smi_msg_received);
 
 void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf)
 {
@@ -3544,7 +3677,7 @@ void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf)
        }
        rcu_read_unlock();
 }
-
+EXPORT_SYMBOL(ipmi_smi_watchdog_pretimeout);
 
 static struct ipmi_smi_msg *
 smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg,
@@ -3552,14 +3685,16 @@ smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg,
 {
        struct ipmi_smi_msg *smi_msg = ipmi_alloc_smi_msg();
        if (!smi_msg)
-               /* If we can't allocate the message, then just return, we
-                  get 4 retries, so this should be ok. */
+               /*
+                * If we can't allocate the message, then just return, we
+                * get 4 retries, so this should be ok.
+                */
                return NULL;
 
        memcpy(smi_msg->data, recv_msg->msg.data, recv_msg->msg.data_len);
        smi_msg->data_size = recv_msg->msg.data_len;
        smi_msg->msgid = STORE_SEQ_IN_MSGID(seq, seqid);
-               
+
 #ifdef DEBUG_MSGING
        {
                int m;
@@ -3594,28 +3729,26 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent,
                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++;
+                       ipmi_inc_stat(intf, timed_out_ipmb_broadcasts);
                else if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE)
-                       intf->timed_out_lan_commands++;
+                       ipmi_inc_stat(intf, timed_out_lan_commands);
                else
-                       intf->timed_out_ipmb_commands++;
-               spin_unlock(&intf->counter_lock);
+                       ipmi_inc_stat(intf, timed_out_ipmb_commands);
        } 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. */
+               /*
+                * 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++;
+                       ipmi_inc_stat(intf, retransmitted_lan_commands);
                else
-                       intf->retransmitted_ipmb_commands++;
-               spin_unlock(&intf->counter_lock);
+                       ipmi_inc_stat(intf, retransmitted_ipmb_commands);
 
                smi_msg = smi_from_recv_msg(intf, ent->recv_msg, slot,
                                            ent->seqid);
@@ -3624,11 +3757,13 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent,
 
                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. */
+               /*
+                * 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.
+                */
                handlers = intf->handlers;
                if (handlers)
                        intf->handlers->sender(intf->send_info,
@@ -3659,16 +3794,20 @@ static void ipmi_timeout_handler(long timeout_period)
                                list_del(&smi_msg->link);
                                ipmi_free_smi_msg(smi_msg);
                        } else {
-                               /* To preserve message order, quit if we
-                                  can't handle a message. */
+                               /*
+                                * To preserve message order, quit if we
+                                * can't handle a message.
+                                */
                                break;
                        }
                }
                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. */
+               /*
+                * Go through the seq table and find any messages that
+                * have timed out, putting them in the timeouts
+                * list.
+                */
                INIT_LIST_HEAD(&timeouts);
                spin_lock_irqsave(&intf->seq_lock, flags);
                for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++)
@@ -3694,8 +3833,7 @@ static void ipmi_timeout_handler(long timeout_period)
                                intf->auto_maintenance_timeout
                                        -= timeout_period;
                                if (!intf->maintenance_mode
-                                   && (intf->auto_maintenance_timeout <= 0))
-                               {
+                                   && (intf->auto_maintenance_timeout <= 0)) {
                                        intf->maintenance_mode_enable = 0;
                                        maintenance_mode_update(intf);
                                }
@@ -3713,8 +3851,10 @@ static void ipmi_request_event(void)
        struct ipmi_smi_handlers *handlers;
 
        rcu_read_lock();
-       /* Called from the timer, no need to check if handlers is
-        * valid. */
+       /*
+        * Called from the timer, no need to check if handlers is
+        * valid.
+        */
        list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
                /* No event requests when in maintenance mode. */
                if (intf->maintenance_mode_enable)
@@ -3735,10 +3875,12 @@ static struct timer_list ipmi_timer;
 /* How many jiffies does it take to get to the timeout time. */
 #define IPMI_TIMEOUT_JIFFIES   ((IPMI_TIMEOUT_TIME * HZ) / 1000)
 
-/* Request events from the queue every second (this is the number of
-   IPMI_TIMEOUT_TIMES between event requests).  Hopefully, in the
-   future, IPMI will add a way to know immediately if an event is in
-   the queue and this silliness can go away. */
+/*
+ * Request events from the queue every second (this is the number of
+ * IPMI_TIMEOUT_TIMES between event requests).  Hopefully, in the
+ * future, IPMI will add a way to know immediately if an event is in
+ * the queue and this silliness can go away.
+ */
 #define IPMI_REQUEST_EV_TIME   (1000 / (IPMI_TIMEOUT_TIME))
 
 static atomic_t stop_operation;
@@ -3782,6 +3924,7 @@ struct ipmi_smi_msg *ipmi_alloc_smi_msg(void)
        }
        return rv;
 }
+EXPORT_SYMBOL(ipmi_alloc_smi_msg);
 
 static void free_recv_msg(struct ipmi_recv_msg *msg)
 {
@@ -3789,7 +3932,7 @@ static void free_recv_msg(struct ipmi_recv_msg *msg)
        kfree(msg);
 }
 
-struct ipmi_recv_msg *ipmi_alloc_recv_msg(void)
+static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void)
 {
        struct ipmi_recv_msg *rv;
 
@@ -3808,6 +3951,7 @@ void ipmi_free_recv_msg(struct ipmi_recv_msg *msg)
                kref_put(&msg->user->refcount, free_user);
        msg->done(msg);
 }
+EXPORT_SYMBOL(ipmi_free_recv_msg);
 
 #ifdef CONFIG_IPMI_PANIC_EVENT
 
@@ -3825,8 +3969,7 @@ static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
        if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
            && (msg->msg.netfn == IPMI_NETFN_SENSOR_EVENT_RESPONSE)
            && (msg->msg.cmd == IPMI_GET_EVENT_RECEIVER_CMD)
-           && (msg->msg.data[0] == IPMI_CC_NO_ERROR))
-       {
+           && (msg->msg.data[0] == IPMI_CC_NO_ERROR)) {
                /* A get event receiver command, save it. */
                intf->event_receiver = msg->msg.data[1];
                intf->event_receiver_lun = msg->msg.data[2] & 0x3;
@@ -3838,10 +3981,11 @@ static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
        if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
            && (msg->msg.netfn == IPMI_NETFN_APP_RESPONSE)
            && (msg->msg.cmd == IPMI_GET_DEVICE_ID_CMD)
-           && (msg->msg.data[0] == IPMI_CC_NO_ERROR))
-       {
-               /* A get device id command, save if we are an event
-                  receiver or generator. */
+           && (msg->msg.data[0] == IPMI_CC_NO_ERROR)) {
+               /*
+                * A get device id command, save if we are an event
+                * receiver or generator.
+                */
                intf->local_sel_device = (msg->msg.data[6] >> 2) & 1;
                intf->local_event_generator = (msg->msg.data[6] >> 5) & 1;
        }
@@ -3874,8 +4018,10 @@ static void send_panic_events(char *str)
        data[4] = 0x6f; /* Sensor specific, IPMI table 36-1 */
        data[5] = 0xa1; /* Runtime stop OEM bytes 2 & 3. */
 
-       /* Put a few breadcrumbs in.  Hopefully later we can add more things
-          to make the panic events more useful. */
+       /*
+        * Put a few breadcrumbs in.  Hopefully later we can add more things
+        * to make the panic events more useful.
+        */
        if (str) {
                data[3] = str[0];
                data[6] = str[1];
@@ -3891,6 +4037,7 @@ static void send_panic_events(char *str)
                        /* Interface is not ready. */
                        continue;
 
+               intf->run_to_completion = 1;
                /* Send the event announcing the panic. */
                intf->handlers->set_run_to_completion(intf->send_info, 1);
                i_ipmi_request(NULL,
@@ -3908,9 +4055,11 @@ static void send_panic_events(char *str)
        }
 
 #ifdef CONFIG_IPMI_PANIC_STRING
-       /* On every interface, dump a bunch of OEM event holding the
-          string. */
-       if (!str) 
+       /*
+        * On every interface, dump a bunch of OEM event holding the
+        * string.
+        */
+       if (!str)
                return;
 
        /* For every registered interface, send the event. */
@@ -3931,11 +4080,13 @@ static void send_panic_events(char *str)
                 */
                smp_rmb();
 
-               /* First job here is to figure out where to send the
-                  OEM events.  There's no way in IPMI to send OEM
-                  events using an event send command, so we have to
-                  find the SEL to put them in and stick them in
-                  there. */
+               /*
+                * First job here is to figure out where to send the
+                * OEM events.  There's no way in IPMI to send OEM
+                * events using an event send command, so we have to
+                * find the SEL to put them in and stick them in
+                * there.
+                */
 
                /* Get capabilities from the get device id. */
                intf->local_sel_device = 0;
@@ -3983,24 +4134,29 @@ static void send_panic_events(char *str)
                }
                intf->null_user_handler = NULL;
 
-               /* Validate the event receiver.  The low bit must not
-                  be 1 (it must be a valid IPMB address), it cannot
-                  be zero, and it must not be my address. */
-                if (((intf->event_receiver & 1) == 0)
+               /*
+                * Validate the event receiver.  The low bit must not
+                * be 1 (it must be a valid IPMB address), it cannot
+                * be zero, and it must not be my address.
+                */
+               if (((intf->event_receiver & 1) == 0)
                    && (intf->event_receiver != 0)
-                   && (intf->event_receiver != intf->channels[0].address))
-               {
-                       /* The event receiver is valid, send an IPMB
-                          message. */
+                   && (intf->event_receiver != intf->channels[0].address)) {
+                       /*
+                        * The event receiver is valid, send an IPMB
+                        * message.
+                        */
                        ipmb = (struct ipmi_ipmb_addr *) &addr;
                        ipmb->addr_type = IPMI_IPMB_ADDR_TYPE;
                        ipmb->channel = 0; /* FIXME - is this right? */
                        ipmb->lun = intf->event_receiver_lun;
                        ipmb->slave_addr = intf->event_receiver;
                } else if (intf->local_sel_device) {
-                       /* The event receiver was not valid (or was
-                          me), but I am an SEL device, just dump it
-                          in my SEL. */
+                       /*
+                        * The event receiver was not valid (or was
+                        * me), but I am an SEL device, just dump it
+                        * in my SEL.
+                        */
                        si = (struct ipmi_system_interface_addr *) &addr;
                        si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
                        si->channel = IPMI_BMC_CHANNEL;
@@ -4008,7 +4164,6 @@ static void send_panic_events(char *str)
                } else
                        continue; /* No where to send the event. */
 
-               
                msg.netfn = IPMI_NETFN_STORAGE_REQUEST; /* Storage. */
                msg.cmd = IPMI_ADD_SEL_ENTRY_CMD;
                msg.data = data;
@@ -4025,8 +4180,10 @@ static void send_panic_events(char *str)
                        data[2] = 0xf0; /* OEM event without timestamp. */
                        data[3] = intf->channels[0].address;
                        data[4] = j++; /* sequence # */
-                       /* Always give 11 bytes, so strncpy will fill
-                          it with zeroes for me. */
+                       /*
+                        * Always give 11 bytes, so strncpy will fill
+                        * it with zeroes for me.
+                        */
                        strncpy(data+5, p, 11);
                        p += size;
 
@@ -4043,7 +4200,7 @@ static void send_panic_events(char *str)
                                       intf->channels[0].lun,
                                       0, 1); /* no retry, and no wait. */
                }
-       }       
+       }
 #endif /* CONFIG_IPMI_PANIC_STRING */
 }
 #endif /* CONFIG_IPMI_PANIC_EVENT */
@@ -4052,7 +4209,7 @@ static int has_panicked;
 
 static int panic_event(struct notifier_block *this,
                       unsigned long         event,
-                       void                  *ptr)
+                      void                  *ptr)
 {
        ipmi_smi_t intf;
 
@@ -4066,6 +4223,7 @@ static int panic_event(struct notifier_block *this,
                        /* Interface is not ready. */
                        continue;
 
+               intf->run_to_completion = 1;
                intf->handlers->set_run_to_completion(intf->send_info, 1);
        }
 
@@ -4133,11 +4291,16 @@ static __exit void cleanup_ipmi(void)
 
        atomic_notifier_chain_unregister(&panic_notifier_list, &panic_block);
 
-       /* This can't be called if any interfaces exist, so no worry about
-          shutting down the interfaces. */
+       /*
+        * This can't be called if any interfaces exist, so no worry
+        * about shutting down the interfaces.
+        */
 
-       /* Tell the timer to stop, then wait for it to stop.  This avoids
-          problems with race conditions removing the timer here. */
+       /*
+        * Tell the timer to stop, then wait for it to stop.  This
+        * avoids problems with race conditions removing the timer
+        * here.
+        */
        atomic_inc(&stop_operation);
        del_timer_sync(&ipmi_timer);
 
@@ -4164,31 +4327,6 @@ module_exit(cleanup_ipmi);
 module_init(ipmi_init_msghandler_mod);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
-MODULE_DESCRIPTION("Incoming and outgoing message routing for an IPMI interface.");
+MODULE_DESCRIPTION("Incoming and outgoing message routing for an IPMI"
+                  " interface.");
 MODULE_VERSION(IPMI_DRIVER_VERSION);
-
-EXPORT_SYMBOL(ipmi_create_user);
-EXPORT_SYMBOL(ipmi_destroy_user);
-EXPORT_SYMBOL(ipmi_get_version);
-EXPORT_SYMBOL(ipmi_request_settime);
-EXPORT_SYMBOL(ipmi_request_supply_msgs);
-EXPORT_SYMBOL(ipmi_poll_interface);
-EXPORT_SYMBOL(ipmi_register_smi);
-EXPORT_SYMBOL(ipmi_unregister_smi);
-EXPORT_SYMBOL(ipmi_register_for_cmd);
-EXPORT_SYMBOL(ipmi_unregister_for_cmd);
-EXPORT_SYMBOL(ipmi_smi_msg_received);
-EXPORT_SYMBOL(ipmi_smi_watchdog_pretimeout);
-EXPORT_SYMBOL(ipmi_alloc_smi_msg);
-EXPORT_SYMBOL(ipmi_addr_length);
-EXPORT_SYMBOL(ipmi_validate_addr);
-EXPORT_SYMBOL(ipmi_set_gets_events);
-EXPORT_SYMBOL(ipmi_smi_watcher_register);
-EXPORT_SYMBOL(ipmi_smi_watcher_unregister);
-EXPORT_SYMBOL(ipmi_set_my_address);
-EXPORT_SYMBOL(ipmi_get_my_address);
-EXPORT_SYMBOL(ipmi_set_my_LUN);
-EXPORT_SYMBOL(ipmi_get_my_LUN);
-EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
-EXPORT_SYMBOL(ipmi_user_set_run_to_completion);
-EXPORT_SYMBOL(ipmi_free_recv_msg);
index b86186de7f07ea8486602cfb7b70b6a450bb21a1..a261bd735dfbddd724974218bc5006c3ccabd30d 100644 (file)
@@ -87,7 +87,10 @@ MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog "
 
 /* parameter definition to allow user to flag power cycle */
 module_param(poweroff_powercycle, int, 0644);
-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.");
+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;
@@ -95,22 +98,25 @@ static unsigned int prod_id;
 static unsigned char capabilities;
 static unsigned char ipmi_version;
 
-/* We use our own messages for this operation, we don't let the system
-   allocate them, since we may be in a panic situation.  The whole
-   thing is single-threaded, anyway, so multiple messages are not
-   required. */
+/*
+ * We use our own messages for this operation, we don't let the system
+ * allocate them, since we may be in a panic situation.  The whole
+ * thing is single-threaded, anyway, so multiple messages are not
+ * required.
+ */
+static atomic_t dummy_count = ATOMIC_INIT(0);
 static void dummy_smi_free(struct ipmi_smi_msg *msg)
 {
+       atomic_dec(&dummy_count);
 }
 static void dummy_recv_free(struct ipmi_recv_msg *msg)
 {
+       atomic_dec(&dummy_count);
 }
-static struct ipmi_smi_msg halt_smi_msg =
-{
+static struct ipmi_smi_msg halt_smi_msg = {
        .done = dummy_smi_free
 };
-static struct ipmi_recv_msg halt_recv_msg =
-{
+static struct ipmi_recv_msg halt_recv_msg = {
        .done = dummy_recv_free
 };
 
@@ -127,8 +133,7 @@ static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data)
                complete(comp);
 }
 
-static struct ipmi_user_hndl ipmi_poweroff_handler =
-{
+static struct ipmi_user_hndl ipmi_poweroff_handler = {
        .ipmi_recv_hndl = receive_handler
 };
 
@@ -152,17 +157,28 @@ static int ipmi_request_wait_for_response(ipmi_user_t            user,
        return halt_recv_msg.msg.data[0];
 }
 
-/* We are in run-to-completion mode, no completion is desired. */
+/* Wait for message to complete, spinning. */
 static int ipmi_request_in_rc_mode(ipmi_user_t            user,
                                   struct ipmi_addr       *addr,
                                   struct kernel_ipmi_msg *send_msg)
 {
        int rv;
 
+       atomic_set(&dummy_count, 2);
        rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL,
                                      &halt_smi_msg, &halt_recv_msg, 0);
-       if (rv)
+       if (rv) {
+               atomic_set(&dummy_count, 0);
                return rv;
+       }
+
+       /*
+        * Spin until our message is done.
+        */
+       while (atomic_read(&dummy_count) > 0) {
+               ipmi_poll_interface(user);
+               cpu_relax();
+       }
 
        return halt_recv_msg.msg.data[0];
 }
@@ -184,47 +200,47 @@ static int ipmi_request_in_rc_mode(ipmi_user_t            user,
 
 static void (*atca_oem_poweroff_hook)(ipmi_user_t user);
 
-static void pps_poweroff_atca (ipmi_user_t user)
+static void pps_poweroff_atca(ipmi_user_t user)
 {
-        struct ipmi_system_interface_addr smi_addr;
-        struct kernel_ipmi_msg            send_msg;
-        int                               rv;
-        /*
-         * Configure IPMI address for local access
-         */
-        smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
-        smi_addr.channel = IPMI_BMC_CHANNEL;
-        smi_addr.lun = 0;
-
-        printk(KERN_INFO PFX "PPS powerdown hook used");
-
-        send_msg.netfn = IPMI_NETFN_OEM;
-        send_msg.cmd = IPMI_ATCA_PPS_GRACEFUL_RESTART;
-        send_msg.data = IPMI_ATCA_PPS_IANA;
-        send_msg.data_len = 3;
-        rv = ipmi_request_in_rc_mode(user,
-                                  (struct ipmi_addr *) &smi_addr,
-                                   &send_msg);
-        if (rv && rv != IPMI_UNKNOWN_ERR_COMPLETION_CODE) {
-                printk(KERN_ERR PFX "Unable to send ATCA ,"
-                       " IPMI error 0x%x\n", rv);
-        }
+       struct ipmi_system_interface_addr smi_addr;
+       struct kernel_ipmi_msg            send_msg;
+       int                               rv;
+       /*
+        * Configure IPMI address for local access
+        */
+       smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+       smi_addr.channel = IPMI_BMC_CHANNEL;
+       smi_addr.lun = 0;
+
+       printk(KERN_INFO PFX "PPS powerdown hook used");
+
+       send_msg.netfn = IPMI_NETFN_OEM;
+       send_msg.cmd = IPMI_ATCA_PPS_GRACEFUL_RESTART;
+       send_msg.data = IPMI_ATCA_PPS_IANA;
+       send_msg.data_len = 3;
+       rv = ipmi_request_in_rc_mode(user,
+                                    (struct ipmi_addr *) &smi_addr,
+                                    &send_msg);
+       if (rv && rv != IPMI_UNKNOWN_ERR_COMPLETION_CODE) {
+               printk(KERN_ERR PFX "Unable to send ATCA ,"
+                      " IPMI error 0x%x\n", rv);
+       }
        return;
 }
 
-static int ipmi_atca_detect (ipmi_user_t user)
+static int ipmi_atca_detect(ipmi_user_t user)
 {
        struct ipmi_system_interface_addr smi_addr;
        struct kernel_ipmi_msg            send_msg;
        int                               rv;
        unsigned char                     data[1];
 
-        /*
-         * Configure IPMI address for local access
-         */
-        smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
-        smi_addr.channel = IPMI_BMC_CHANNEL;
-        smi_addr.lun = 0;
+       /*
+        * Configure IPMI address for local access
+        */
+       smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+       smi_addr.channel = IPMI_BMC_CHANNEL;
+       smi_addr.lun = 0;
 
        /*
         * Use get address info to check and see if we are ATCA
@@ -238,28 +254,30 @@ static int ipmi_atca_detect (ipmi_user_t user)
                                            (struct ipmi_addr *) &smi_addr,
                                            &send_msg);
 
-        printk(KERN_INFO PFX "ATCA Detect mfg 0x%X prod 0x%X\n", mfg_id, prod_id);
-        if((mfg_id == IPMI_MOTOROLA_MANUFACTURER_ID)
-            && (prod_id == IPMI_MOTOROLA_PPS_IPMC_PRODUCT_ID)) {
-               printk(KERN_INFO PFX "Installing Pigeon Point Systems Poweroff Hook\n");
+       printk(KERN_INFO PFX "ATCA Detect mfg 0x%X prod 0x%X\n",
+              mfg_id, prod_id);
+       if ((mfg_id == IPMI_MOTOROLA_MANUFACTURER_ID)
+           && (prod_id == IPMI_MOTOROLA_PPS_IPMC_PRODUCT_ID)) {
+               printk(KERN_INFO PFX
+                      "Installing Pigeon Point Systems Poweroff Hook\n");
                atca_oem_poweroff_hook = pps_poweroff_atca;
        }
        return !rv;
 }
 
-static void ipmi_poweroff_atca (ipmi_user_t user)
+static void ipmi_poweroff_atca(ipmi_user_t user)
 {
        struct ipmi_system_interface_addr smi_addr;
        struct kernel_ipmi_msg            send_msg;
        int                               rv;
        unsigned char                     data[4];
 
-        /*
-         * Configure IPMI address for local access
-         */
-        smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
-        smi_addr.channel = IPMI_BMC_CHANNEL;
-        smi_addr.lun = 0;
+       /*
+        * Configure IPMI address for local access
+        */
+       smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+       smi_addr.channel = IPMI_BMC_CHANNEL;
+       smi_addr.lun = 0;
 
        printk(KERN_INFO PFX "Powering down via ATCA power command\n");
 
@@ -273,23 +291,24 @@ static void ipmi_poweroff_atca (ipmi_user_t user)
        data[2] = 0; /* Power Level */
        data[3] = 0; /* Don't change saved presets */
        send_msg.data = data;
-       send_msg.data_len = sizeof (data);
+       send_msg.data_len = sizeof(data);
        rv = ipmi_request_in_rc_mode(user,
                                     (struct ipmi_addr *) &smi_addr,
                                     &send_msg);
-        /** At this point, the system may be shutting down, and most
-         ** serial drivers (if used) will have interrupts turned off
-         ** it may be better to ignore IPMI_UNKNOWN_ERR_COMPLETION_CODE
-         ** return code
-         **/
-        if (rv && rv != IPMI_UNKNOWN_ERR_COMPLETION_CODE) {
+       /*
+        * At this point, the system may be shutting down, and most
+        * serial drivers (if used) will have interrupts turned off
+        * it may be better to ignore IPMI_UNKNOWN_ERR_COMPLETION_CODE
+        * return code
+        */
+       if (rv && rv != IPMI_UNKNOWN_ERR_COMPLETION_CODE) {
                printk(KERN_ERR PFX "Unable to send ATCA powerdown message,"
                       " IPMI error 0x%x\n", rv);
                goto out;
        }
 
-       if(atca_oem_poweroff_hook)
-               return atca_oem_poweroff_hook(user);
+       if (atca_oem_poweroff_hook)
+               atca_oem_poweroff_hook(user);
  out:
        return;
 }
@@ -310,13 +329,13 @@ static void ipmi_poweroff_atca (ipmi_user_t user)
 #define IPMI_CPI1_PRODUCT_ID           0x000157
 #define IPMI_CPI1_MANUFACTURER_ID      0x0108
 
-static int ipmi_cpi1_detect (ipmi_user_t user)
+static int ipmi_cpi1_detect(ipmi_user_t user)
 {
        return ((mfg_id == IPMI_CPI1_MANUFACTURER_ID)
                && (prod_id == IPMI_CPI1_PRODUCT_ID));
 }
 
-static void ipmi_poweroff_cpi1 (ipmi_user_t user)
+static void ipmi_poweroff_cpi1(ipmi_user_t user)
 {
        struct ipmi_system_interface_addr smi_addr;
        struct ipmi_ipmb_addr             ipmb_addr;
@@ -328,12 +347,12 @@ static void ipmi_poweroff_cpi1 (ipmi_user_t user)
        unsigned char                     aer_addr;
        unsigned char                     aer_lun;
 
-        /*
-         * Configure IPMI address for local access
-         */
-        smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
-        smi_addr.channel = IPMI_BMC_CHANNEL;
-        smi_addr.lun = 0;
+       /*
+        * Configure IPMI address for local access
+        */
+       smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+       smi_addr.channel = IPMI_BMC_CHANNEL;
+       smi_addr.lun = 0;
 
        printk(KERN_INFO PFX "Powering down via CPI1 power command\n");
 
@@ -425,7 +444,7 @@ static void ipmi_poweroff_cpi1 (ipmi_user_t user)
  */
 
 #define DELL_IANA_MFR_ID {0xA2, 0x02, 0x00}
-static int ipmi_dell_chassis_detect (ipmi_user_t user)
+static int ipmi_dell_chassis_detect(ipmi_user_t user)
 {
        const char ipmi_version_major = ipmi_version & 0xF;
        const char ipmi_version_minor = (ipmi_version >> 4) & 0xF;
@@ -444,25 +463,25 @@ static int ipmi_dell_chassis_detect (ipmi_user_t user)
 #define IPMI_NETFN_CHASSIS_REQUEST     0
 #define IPMI_CHASSIS_CONTROL_CMD       0x02
 
-static int ipmi_chassis_detect (ipmi_user_t user)
+static int ipmi_chassis_detect(ipmi_user_t user)
 {
        /* Chassis support, use it. */
        return (capabilities & 0x80);
 }
 
-static void ipmi_poweroff_chassis (ipmi_user_t user)
+static void ipmi_poweroff_chassis(ipmi_user_t user)
 {
        struct ipmi_system_interface_addr smi_addr;
        struct kernel_ipmi_msg            send_msg;
        int                               rv;
        unsigned char                     data[1];
 
-        /*
-         * Configure IPMI address for local access
-         */
-        smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
-        smi_addr.channel = IPMI_BMC_CHANNEL;
-        smi_addr.lun = 0;
+       /*
+        * Configure IPMI address for local access
+        */
+       smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+       smi_addr.channel = IPMI_BMC_CHANNEL;
+       smi_addr.lun = 0;
 
  powercyclefailed:
        printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n",
@@ -525,15 +544,13 @@ static struct poweroff_function poweroff_functions[] = {
 
 
 /* Called on a powerdown request. */
-static void ipmi_poweroff_function (void)
+static void ipmi_poweroff_function(void)
 {
        if (!ready)
                return;
 
        /* Use run-to-completion mode, since interrupts may be off. */
-       ipmi_user_set_run_to_completion(ipmi_user, 1);
        specific_poweroff_func(ipmi_user);
-       ipmi_user_set_run_to_completion(ipmi_user, 0);
 }
 
 /* Wait for an IPMI interface to be installed, the first one installed
@@ -561,13 +578,13 @@ static void ipmi_po_new_smi(int if_num, struct device *device)
 
        ipmi_ifnum = if_num;
 
-        /*
-         * Do a get device ide and store some results, since this is
+       /*
+        * Do a get device ide and store some results, since this is
         * used by several functions.
-         */
-        smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
-        smi_addr.channel = IPMI_BMC_CHANNEL;
-        smi_addr.lun = 0;
+        */
+       smi_addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+       smi_addr.channel = IPMI_BMC_CHANNEL;
+       smi_addr.lun = 0;
 
        send_msg.netfn = IPMI_NETFN_APP_REQUEST;
        send_msg.cmd = IPMI_GET_DEVICE_ID_CMD;
@@ -632,8 +649,7 @@ static void ipmi_po_smi_gone(int if_num)
        pm_power_off = old_poweroff_func;
 }
 
-static struct ipmi_smi_watcher smi_watcher =
-{
+static struct ipmi_smi_watcher smi_watcher = {
        .owner    = THIS_MODULE,
        .new_smi  = ipmi_po_new_smi,
        .smi_gone = ipmi_po_smi_gone
@@ -675,12 +691,12 @@ static struct ctl_table_header *ipmi_table_header;
 /*
  * Startup and shutdown functions.
  */
-static int ipmi_poweroff_init (void)
+static int ipmi_poweroff_init(void)
 {
        int rv;
 
-       printk (KERN_INFO "Copyright (C) 2004 MontaVista Software -"
-               " IPMI Powerdown via sys_reboot.\n");
+       printk(KERN_INFO "Copyright (C) 2004 MontaVista Software -"
+              " IPMI Powerdown via sys_reboot.\n");
 
        if (poweroff_powercycle)
                printk(KERN_INFO PFX "Power cycle is enabled.\n");
index 4f560d0bb8089fa296dadeaee3a21bfb7a91b052..5a5455585c1d278bd770a784fd5e1df603df85e3 100644 (file)
@@ -80,7 +80,7 @@
 #define SI_USEC_PER_JIFFY      (1000000/HZ)
 #define SI_TIMEOUT_JIFFIES     (SI_TIMEOUT_TIME_USEC/SI_USEC_PER_JIFFY)
 #define SI_SHORT_TIMEOUT_USEC  250 /* .25ms when the SM request a
-                                       short timeout */
+                                     short timeout */
 
 /* Bit for BMC global enables. */
 #define IPMI_BMC_RCV_MSG_INTR     0x01
@@ -114,14 +114,61 @@ static char *si_to_str[] = { "kcs", "smic", "bt" };
 
 #define DEVICE_NAME "ipmi_si"
 
-static struct device_driver ipmi_driver =
-{
+static struct device_driver ipmi_driver = {
        .name = DEVICE_NAME,
        .bus = &platform_bus_type
 };
 
-struct smi_info
-{
+
+/*
+ * Indexes into stats[] in smi_info below.
+ */
+enum si_stat_indexes {
+       /*
+        * Number of times the driver requested a timer while an operation
+        * was in progress.
+        */
+       SI_STAT_short_timeouts = 0,
+
+       /*
+        * Number of times the driver requested a timer while nothing was in
+        * progress.
+        */
+       SI_STAT_long_timeouts,
+
+       /* Number of times the interface was idle while being polled. */
+       SI_STAT_idles,
+
+       /* Number of interrupts the driver handled. */
+       SI_STAT_interrupts,
+
+       /* Number of time the driver got an ATTN from the hardware. */
+       SI_STAT_attentions,
+
+       /* Number of times the driver requested flags from the hardware. */
+       SI_STAT_flag_fetches,
+
+       /* Number of times the hardware didn't follow the state machine. */
+       SI_STAT_hosed_count,
+
+       /* Number of completed messages. */
+       SI_STAT_complete_transactions,
+
+       /* Number of IPMI events received from the hardware. */
+       SI_STAT_events,
+
+       /* Number of watchdog pretimeouts. */
+       SI_STAT_watchdog_pretimeouts,
+
+       /* Number of asyncronous messages received. */
+       SI_STAT_incoming_messages,
+
+
+       /* This *must* remain last, add new values above this. */
+       SI_NUM_STATS
+};
+
+struct smi_info {
        int                    intf_num;
        ipmi_smi_t             intf;
        struct si_sm_data      *si_sm;
@@ -134,8 +181,10 @@ struct smi_info
        struct ipmi_smi_msg    *curr_msg;
        enum si_intf_state     si_state;
 
-       /* Used to handle the various types of I/O that can occur with
-           IPMI */
+       /*
+        * Used to handle the various types of I/O that can occur with
+        * IPMI
+        */
        struct si_sm_io io;
        int (*io_setup)(struct smi_info *info);
        void (*io_cleanup)(struct smi_info *info);
@@ -146,15 +195,18 @@ struct smi_info
        void (*addr_source_cleanup)(struct smi_info *info);
        void *addr_source_data;
 
-       /* Per-OEM handler, called from handle_flags().
-          Returns 1 when handle_flags() needs to be re-run
-          or 0 indicating it set si_state itself.
-       */
+       /*
+        * Per-OEM handler, called from handle_flags().  Returns 1
+        * when handle_flags() needs to be re-run or 0 indicating it
+        * set si_state itself.
+        */
        int (*oem_data_avail_handler)(struct smi_info *smi_info);
 
-       /* Flags from the last GET_MSG_FLAGS command, used when an ATTN
-          is set to hold the flags until we are done handling everything
-          from the flags. */
+       /*
+        * Flags from the last GET_MSG_FLAGS command, used when an ATTN
+        * is set to hold the flags until we are done handling everything
+        * from the flags.
+        */
 #define RECEIVE_MSG_AVAIL      0x01
 #define EVENT_MSG_BUFFER_FULL  0x02
 #define WDT_PRE_TIMEOUT_INT    0x08
@@ -162,25 +214,31 @@ struct smi_info
 #define OEM1_DATA_AVAIL     0x40
 #define OEM2_DATA_AVAIL     0x80
 #define OEM_DATA_AVAIL      (OEM0_DATA_AVAIL | \
-                             OEM1_DATA_AVAIL | \
-                             OEM2_DATA_AVAIL)
+                            OEM1_DATA_AVAIL | \
+                            OEM2_DATA_AVAIL)
        unsigned char       msg_flags;
 
-       /* If set to true, this will request events the next time the
-          state machine is idle. */
+       /*
+        * If set to true, this will request events the next time the
+        * state machine is idle.
+        */
        atomic_t            req_events;
 
-       /* If true, run the state machine to completion on every send
-          call.  Generally used after a panic to make sure stuff goes
-          out. */
+       /*
+        * If true, run the state machine to completion on every send
+        * call.  Generally used after a panic to make sure stuff goes
+        * out.
+        */
        int                 run_to_completion;
 
        /* The I/O port of an SI interface. */
        int                 port;
 
-       /* The space between start addresses of the two ports.  For
-          instance, if the first port is 0xca2 and the spacing is 4, then
-          the second port is 0xca6. */
+       /*
+        * The space between start addresses of the two ports.  For
+        * instance, if the first port is 0xca2 and the spacing is 4, then
+        * the second port is 0xca6.
+        */
        unsigned int        spacing;
 
        /* zero if no irq; */
@@ -195,10 +253,12 @@ struct smi_info
        /* Used to gracefully stop the timer without race conditions. */
        atomic_t            stop_operation;
 
-       /* The driver will disable interrupts when it gets into a
-          situation where it cannot handle messages due to lack of
-          memory.  Once that situation clears up, it will re-enable
-          interrupts. */
+       /*
+        * The driver will disable interrupts when it gets into a
+        * situation where it cannot handle messages due to lack of
+        * memory.  Once that situation clears up, it will re-enable
+        * interrupts.
+        */
        int interrupt_disabled;
 
        /* From the get device id response... */
@@ -208,33 +268,28 @@ struct smi_info
        struct device *dev;
        struct platform_device *pdev;
 
-        /* True if we allocated the device, false if it came from
-         * someplace else (like PCI). */
+       /*
+        * True if we allocated the device, false if it came from
+        * someplace else (like PCI).
+        */
        int dev_registered;
 
        /* Slave address, could be reported from DMI. */
        unsigned char slave_addr;
 
        /* Counters and things for the proc filesystem. */
-       spinlock_t count_lock;
-       unsigned long short_timeouts;
-       unsigned long long_timeouts;
-       unsigned long timeout_restarts;
-       unsigned long idles;
-       unsigned long interrupts;
-       unsigned long attentions;
-       unsigned long flag_fetches;
-       unsigned long hosed_count;
-       unsigned long complete_transactions;
-       unsigned long events;
-       unsigned long watchdog_pretimeouts;
-       unsigned long incoming_messages;
-
-        struct task_struct *thread;
+       atomic_t stats[SI_NUM_STATS];
+
+       struct task_struct *thread;
 
        struct list_head link;
 };
 
+#define smi_inc_stat(smi, stat) \
+       atomic_inc(&(smi)->stats[SI_STAT_ ## stat])
+#define smi_get_stat(smi, stat) \
+       ((unsigned int) atomic_read(&(smi)->stats[SI_STAT_ ## stat]))
+
 #define SI_MAX_PARMS 4
 
 static int force_kipmid[SI_MAX_PARMS];
@@ -246,7 +301,7 @@ static int try_smi_init(struct smi_info *smi);
 static void cleanup_one_si(struct smi_info *to_clean);
 
 static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list);
-static int register_xaction_notifier(struct notifier_block * nb)
+static int register_xaction_notifier(struct notifier_block *nb)
 {
        return atomic_notifier_chain_register(&xaction_notifier_list, nb);
 }
@@ -255,7 +310,7 @@ static void deliver_recv_msg(struct smi_info *smi_info,
                             struct ipmi_smi_msg *msg)
 {
        /* Deliver the message to the upper layer with the lock
-           released. */
+          released. */
        spin_unlock(&(smi_info->si_lock));
        ipmi_smi_msg_received(smi_info->intf, msg);
        spin_lock(&(smi_info->si_lock));
@@ -287,9 +342,12 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
        struct timeval t;
 #endif
 
-       /* No need to save flags, we aleady have interrupts off and we
-          already hold the SMI lock. */
-       spin_lock(&(smi_info->msg_lock));
+       /*
+        * No need to save flags, we aleady have interrupts off and we
+        * already hold the SMI lock.
+        */
+       if (!smi_info->run_to_completion)
+               spin_lock(&(smi_info->msg_lock));
 
        /* Pick the high priority queue first. */
        if (!list_empty(&(smi_info->hp_xmit_msgs))) {
@@ -310,7 +368,7 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
                                                link);
 #ifdef DEBUG_TIMING
                do_gettimeofday(&t);
-               printk("**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec);
+               printk(KERN_DEBUG "**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec);
 #endif
                err = atomic_notifier_call_chain(&xaction_notifier_list,
                                0, smi_info);
@@ -322,14 +380,14 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
                        smi_info->si_sm,
                        smi_info->curr_msg->data,
                        smi_info->curr_msg->data_size);
-               if (err) {
+               if (err)
                        return_hosed_msg(smi_info, err);
-               }
 
                rv = SI_SM_CALL_WITHOUT_DELAY;
        }
-       out:
-       spin_unlock(&(smi_info->msg_lock));
+ out:
+       if (!smi_info->run_to_completion)
+               spin_unlock(&(smi_info->msg_lock));
 
        return rv;
 }
@@ -338,8 +396,10 @@ static void start_enable_irq(struct smi_info *smi_info)
 {
        unsigned char msg[2];
 
-       /* If we are enabling interrupts, we have to tell the
-          BMC to use them. */
+       /*
+        * If we are enabling interrupts, we have to tell the
+        * BMC to use them.
+        */
        msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
        msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
 
@@ -371,10 +431,12 @@ static void start_clear_flags(struct smi_info *smi_info)
        smi_info->si_state = SI_CLEARING_FLAGS;
 }
 
-/* When we have a situtaion where we run out of memory and cannot
-   allocate messages, we just leave them in the BMC and run the system
-   polled until we can allocate some memory.  Once we have some
-   memory, we will re-enable the interrupt. */
+/*
+ * When we have a situtaion where we run out of memory and cannot
+ * allocate messages, we just leave them in the BMC and run the system
+ * polled until we can allocate some memory.  Once we have some
+ * memory, we will re-enable the interrupt.
+ */
 static inline void disable_si_irq(struct smi_info *smi_info)
 {
        if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
@@ -396,9 +458,7 @@ static void handle_flags(struct smi_info *smi_info)
  retry:
        if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) {
                /* Watchdog pre-timeout */
-               spin_lock(&smi_info->count_lock);
-               smi_info->watchdog_pretimeouts++;
-               spin_unlock(&smi_info->count_lock);
+               smi_inc_stat(smi_info, watchdog_pretimeouts);
 
                start_clear_flags(smi_info);
                smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT;
@@ -444,12 +504,11 @@ static void handle_flags(struct smi_info *smi_info)
                        smi_info->curr_msg->data_size);
                smi_info->si_state = SI_GETTING_EVENTS;
        } else if (smi_info->msg_flags & OEM_DATA_AVAIL &&
-                  smi_info->oem_data_avail_handler) {
+                  smi_info->oem_data_avail_handler) {
                if (smi_info->oem_data_avail_handler(smi_info))
                        goto retry;
-       } else {
+       } else
                smi_info->si_state = SI_NORMAL;
-       }
 }
 
 static void handle_transaction_done(struct smi_info *smi_info)
@@ -459,7 +518,7 @@ static void handle_transaction_done(struct smi_info *smi_info)
        struct timeval t;
 
        do_gettimeofday(&t);
-       printk("**Done: %d.%9.9d\n", t.tv_sec, t.tv_usec);
+       printk(KERN_DEBUG "**Done: %d.%9.9d\n", t.tv_sec, t.tv_usec);
 #endif
        switch (smi_info->si_state) {
        case SI_NORMAL:
@@ -472,9 +531,11 @@ static void handle_transaction_done(struct smi_info *smi_info)
                                smi_info->curr_msg->rsp,
                                IPMI_MAX_MSG_LENGTH);
 
-               /* Do this here becase deliver_recv_msg() releases the
-                  lock, and a new message can be put in during the
-                  time the lock is released. */
+               /*
+                * Do this here becase deliver_recv_msg() releases the
+                * lock, and a new message can be put in during the
+                * time the lock is released.
+                */
                msg = smi_info->curr_msg;
                smi_info->curr_msg = NULL;
                deliver_recv_msg(smi_info, msg);
@@ -488,12 +549,13 @@ static void handle_transaction_done(struct smi_info *smi_info)
                /* We got the flags from the SMI, now handle them. */
                len = smi_info->handlers->get_result(smi_info->si_sm, msg, 4);
                if (msg[2] != 0) {
-                       /* Error fetching flags, just give up for
-                          now. */
+                       /* Error fetching flags, just give up for now. */
                        smi_info->si_state = SI_NORMAL;
                } else if (len < 4) {
-                       /* Hmm, no flags.  That's technically illegal, but
-                          don't use uninitialized data. */
+                       /*
+                        * Hmm, no flags.  That's technically illegal, but
+                        * don't use uninitialized data.
+                        */
                        smi_info->si_state = SI_NORMAL;
                } else {
                        smi_info->msg_flags = msg[3];
@@ -530,9 +592,11 @@ static void handle_transaction_done(struct smi_info *smi_info)
                                smi_info->curr_msg->rsp,
                                IPMI_MAX_MSG_LENGTH);
 
-               /* Do this here becase deliver_recv_msg() releases the
-                  lock, and a new message can be put in during the
-                  time the lock is released. */
+               /*
+                * Do this here becase deliver_recv_msg() releases the
+                * lock, and a new message can be put in during the
+                * time the lock is released.
+                */
                msg = smi_info->curr_msg;
                smi_info->curr_msg = NULL;
                if (msg->rsp[2] != 0) {
@@ -543,14 +607,14 @@ static void handle_transaction_done(struct smi_info *smi_info)
                        smi_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
                        handle_flags(smi_info);
                } else {
-                       spin_lock(&smi_info->count_lock);
-                       smi_info->events++;
-                       spin_unlock(&smi_info->count_lock);
-
-                       /* Do this before we deliver the message
-                          because delivering the message releases the
-                          lock and something else can mess with the
-                          state. */
+                       smi_inc_stat(smi_info, events);
+
+                       /*
+                        * Do this before we deliver the message
+                        * because delivering the message releases the
+                        * lock and something else can mess with the
+                        * state.
+                        */
                        handle_flags(smi_info);
 
                        deliver_recv_msg(smi_info, msg);
@@ -566,9 +630,11 @@ static void handle_transaction_done(struct smi_info *smi_info)
                                smi_info->curr_msg->rsp,
                                IPMI_MAX_MSG_LENGTH);
 
-               /* Do this here becase deliver_recv_msg() releases the
-                  lock, and a new message can be put in during the
-                  time the lock is released. */
+               /*
+                * Do this here becase deliver_recv_msg() releases the
+                * lock, and a new message can be put in during the
+                * time the lock is released.
+                */
                msg = smi_info->curr_msg;
                smi_info->curr_msg = NULL;
                if (msg->rsp[2] != 0) {
@@ -579,14 +645,14 @@ static void handle_transaction_done(struct smi_info *smi_info)
                        smi_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
                        handle_flags(smi_info);
                } else {
-                       spin_lock(&smi_info->count_lock);
-                       smi_info->incoming_messages++;
-                       spin_unlock(&smi_info->count_lock);
-
-                       /* Do this before we deliver the message
-                          because delivering the message releases the
-                          lock and something else can mess with the
-                          state. */
+                       smi_inc_stat(smi_info, incoming_messages);
+
+                       /*
+                        * Do this before we deliver the message
+                        * because delivering the message releases the
+                        * lock and something else can mess with the
+                        * state.
+                        */
                        handle_flags(smi_info);
 
                        deliver_recv_msg(smi_info, msg);
@@ -674,69 +740,70 @@ static void handle_transaction_done(struct smi_info *smi_info)
        }
 }
 
-/* Called on timeouts and events.  Timeouts should pass the elapsed
-   time, interrupts should pass in zero.  Must be called with
-   si_lock held and interrupts disabled. */
+/*
+ * Called on timeouts and events.  Timeouts should pass the elapsed
+ * time, interrupts should pass in zero.  Must be called with
+ * si_lock held and interrupts disabled.
+ */
 static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
                                           int time)
 {
        enum si_sm_result si_sm_result;
 
  restart:
-       /* There used to be a loop here that waited a little while
-          (around 25us) before giving up.  That turned out to be
-          pointless, the minimum delays I was seeing were in the 300us
-          range, which is far too long to wait in an interrupt.  So
-          we just run until the state machine tells us something
-          happened or it needs a delay. */
+       /*
+        * There used to be a loop here that waited a little while
+        * (around 25us) before giving up.  That turned out to be
+        * pointless, the minimum delays I was seeing were in the 300us
+        * range, which is far too long to wait in an interrupt.  So
+        * we just run until the state machine tells us something
+        * happened or it needs a delay.
+        */
        si_sm_result = smi_info->handlers->event(smi_info->si_sm, time);
        time = 0;
        while (si_sm_result == SI_SM_CALL_WITHOUT_DELAY)
-       {
                si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0);
-       }
 
-       if (si_sm_result == SI_SM_TRANSACTION_COMPLETE)
-       {
-               spin_lock(&smi_info->count_lock);
-               smi_info->complete_transactions++;
-               spin_unlock(&smi_info->count_lock);
+       if (si_sm_result == SI_SM_TRANSACTION_COMPLETE) {
+               smi_inc_stat(smi_info, complete_transactions);
 
                handle_transaction_done(smi_info);
                si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0);
-       }
-       else if (si_sm_result == SI_SM_HOSED)
-       {
-               spin_lock(&smi_info->count_lock);
-               smi_info->hosed_count++;
-               spin_unlock(&smi_info->count_lock);
+       } else if (si_sm_result == SI_SM_HOSED) {
+               smi_inc_stat(smi_info, hosed_count);
 
-               /* Do the before return_hosed_msg, because that
-                  releases the lock. */
+               /*
+                * Do the before return_hosed_msg, because that
+                * releases the lock.
+                */
                smi_info->si_state = SI_NORMAL;
                if (smi_info->curr_msg != NULL) {
-                       /* If we were handling a user message, format
-                           a response to send to the upper layer to
-                           tell it about the error. */
+                       /*
+                        * If we were handling a user message, format
+                        * a response to send to the upper layer to
+                        * tell it about the error.
+                        */
                        return_hosed_msg(smi_info, IPMI_ERR_UNSPECIFIED);
                }
                si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0);
        }
 
-       /* We prefer handling attn over new messages. */
-       if (si_sm_result == SI_SM_ATTN)
-       {
+       /*
+        * We prefer handling attn over new messages.  But don't do
+        * this if there is not yet an upper layer to handle anything.
+        */
+       if (likely(smi_info->intf) && si_sm_result == SI_SM_ATTN) {
                unsigned char msg[2];
 
-               spin_lock(&smi_info->count_lock);
-               smi_info->attentions++;
-               spin_unlock(&smi_info->count_lock);
+               smi_inc_stat(smi_info, attentions);
 
-               /* Got a attn, send down a get message flags to see
-                   what's causing it.  It would be better to handle
-                   this in the upper layer, but due to the way
-                   interrupts work with the SMI, that's not really
-                   possible. */
+               /*
+                * Got a attn, send down a get message flags to see
+                * what's causing it.  It would be better to handle
+                * this in the upper layer, but due to the way
+                * interrupts work with the SMI, that's not really
+                * possible.
+                */
                msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
                msg[1] = IPMI_GET_MSG_FLAGS_CMD;
 
@@ -748,20 +815,19 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
 
        /* If we are currently idle, try to start the next message. */
        if (si_sm_result == SI_SM_IDLE) {
-               spin_lock(&smi_info->count_lock);
-               smi_info->idles++;
-               spin_unlock(&smi_info->count_lock);
+               smi_inc_stat(smi_info, idles);
 
                si_sm_result = start_next_msg(smi_info);
                if (si_sm_result != SI_SM_IDLE)
                        goto restart;
-        }
+       }
 
        if ((si_sm_result == SI_SM_IDLE)
-           && (atomic_read(&smi_info->req_events)))
-       {
-               /* We are idle and the upper layer requested that I fetch
-                  events, so do so. */
+           && (atomic_read(&smi_info->req_events))) {
+               /*
+                * We are idle and the upper layer requested that I fetch
+                * events, so do so.
+                */
                atomic_set(&smi_info->req_events, 0);
 
                smi_info->curr_msg = ipmi_alloc_smi_msg();
@@ -803,56 +869,50 @@ static void sender(void                *send_info,
                return;
        }
 
-       spin_lock_irqsave(&(smi_info->msg_lock), flags);
 #ifdef DEBUG_TIMING
        do_gettimeofday(&t);
        printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec);
 #endif
 
        if (smi_info->run_to_completion) {
-               /* If we are running to completion, then throw it in
-                  the list and run transactions until everything is
-                  clear.  Priority doesn't matter here. */
+               /*
+                * If we are running to completion, then throw it in
+                * the list and run transactions until everything is
+                * clear.  Priority doesn't matter here.
+                */
+
+               /*
+                * Run to completion means we are single-threaded, no
+                * need for locks.
+                */
                list_add_tail(&(msg->link), &(smi_info->xmit_msgs));
 
-               /* We have to release the msg lock and claim the smi
-                  lock in this case, because of race conditions. */
-               spin_unlock_irqrestore(&(smi_info->msg_lock), flags);
-
-               spin_lock_irqsave(&(smi_info->si_lock), flags);
                result = smi_event_handler(smi_info, 0);
                while (result != SI_SM_IDLE) {
                        udelay(SI_SHORT_TIMEOUT_USEC);
                        result = smi_event_handler(smi_info,
                                                   SI_SHORT_TIMEOUT_USEC);
                }
-               spin_unlock_irqrestore(&(smi_info->si_lock), flags);
                return;
-       } else {
-               if (priority > 0) {
-                       list_add_tail(&(msg->link), &(smi_info->hp_xmit_msgs));
-               } else {
-                       list_add_tail(&(msg->link), &(smi_info->xmit_msgs));
-               }
        }
-       spin_unlock_irqrestore(&(smi_info->msg_lock), flags);
 
-       spin_lock_irqsave(&(smi_info->si_lock), flags);
-       if ((smi_info->si_state == SI_NORMAL)
-           && (smi_info->curr_msg == NULL))
-       {
+       spin_lock_irqsave(&smi_info->msg_lock, flags);
+       if (priority > 0)
+               list_add_tail(&msg->link, &smi_info->hp_xmit_msgs);
+       else
+               list_add_tail(&msg->link, &smi_info->xmit_msgs);
+       spin_unlock_irqrestore(&smi_info->msg_lock, flags);
+
+       spin_lock_irqsave(&smi_info->si_lock, flags);
+       if (smi_info->si_state == SI_NORMAL && smi_info->curr_msg == NULL)
                start_next_msg(smi_info);
-       }
-       spin_unlock_irqrestore(&(smi_info->si_lock), flags);
+       spin_unlock_irqrestore(&smi_info->si_lock, flags);
 }
 
 static void set_run_to_completion(void *send_info, int i_run_to_completion)
 {
        struct smi_info   *smi_info = send_info;
        enum si_sm_result result;
-       unsigned long     flags;
-
-       spin_lock_irqsave(&(smi_info->si_lock), flags);
 
        smi_info->run_to_completion = i_run_to_completion;
        if (i_run_to_completion) {
@@ -863,8 +923,6 @@ static void set_run_to_completion(void *send_info, int i_run_to_completion)
                                                   SI_SHORT_TIMEOUT_USEC);
                }
        }
-
-       spin_unlock_irqrestore(&(smi_info->si_lock), flags);
 }
 
 static int ipmi_thread(void *data)
@@ -878,9 +936,8 @@ static int ipmi_thread(void *data)
                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 */
-               }
+               if (smi_result == SI_SM_CALL_WITHOUT_DELAY)
+                       ; /* do nothing */
                else if (smi_result == SI_SM_CALL_WITH_DELAY)
                        schedule();
                else
@@ -931,7 +988,7 @@ static void smi_timeout(unsigned long data)
        spin_lock_irqsave(&(smi_info->si_lock), flags);
 #ifdef DEBUG_TIMING
        do_gettimeofday(&t);
-       printk("**Timer: %d.%9.9d\n", t.tv_sec, t.tv_usec);
+       printk(KERN_DEBUG "**Timer: %d.%9.9d\n", t.tv_sec, t.tv_usec);
 #endif
        jiffies_now = jiffies;
        time_diff = (((long)jiffies_now - (long)smi_info->last_timeout_jiffies)
@@ -945,23 +1002,19 @@ static void smi_timeout(unsigned long data)
        if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
                /* Running with interrupts, only do long timeouts. */
                smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
-               spin_lock_irqsave(&smi_info->count_lock, flags);
-               smi_info->long_timeouts++;
-               spin_unlock_irqrestore(&smi_info->count_lock, flags);
+               smi_inc_stat(smi_info, long_timeouts);
                goto do_add_timer;
        }
 
-       /* If the state machine asks for a short delay, then shorten
-           the timer timeout. */
+       /*
+        * If the state machine asks for a short delay, then shorten
+        * the timer timeout.
+        */
        if (smi_result == SI_SM_CALL_WITH_DELAY) {
-               spin_lock_irqsave(&smi_info->count_lock, flags);
-               smi_info->short_timeouts++;
-               spin_unlock_irqrestore(&smi_info->count_lock, flags);
+               smi_inc_stat(smi_info, short_timeouts);
                smi_info->si_timer.expires = jiffies + 1;
        } else {
-               spin_lock_irqsave(&smi_info->count_lock, flags);
-               smi_info->long_timeouts++;
-               spin_unlock_irqrestore(&smi_info->count_lock, flags);
+               smi_inc_stat(smi_info, long_timeouts);
                smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
        }
 
@@ -979,13 +1032,11 @@ static irqreturn_t si_irq_handler(int irq, void *data)
 
        spin_lock_irqsave(&(smi_info->si_lock), flags);
 
-       spin_lock(&smi_info->count_lock);
-       smi_info->interrupts++;
-       spin_unlock(&smi_info->count_lock);
+       smi_inc_stat(smi_info, interrupts);
 
 #ifdef DEBUG_TIMING
        do_gettimeofday(&t);
-       printk("**Interrupt: %d.%9.9d\n", t.tv_sec, t.tv_usec);
+       printk(KERN_DEBUG "**Interrupt: %d.%9.9d\n", t.tv_sec, t.tv_usec);
 #endif
        smi_event_handler(smi_info, 0);
        spin_unlock_irqrestore(&(smi_info->si_lock), flags);
@@ -1028,7 +1079,7 @@ static int smi_start_processing(void       *send_info,
         * The BT interface is efficient enough to not need a thread,
         * and there is no need for a thread if we have interrupts.
         */
-       else if ((new_smi->si_type != SI_BT) && (!new_smi->irq))
+       else if ((new_smi->si_type != SI_BT) && (!new_smi->irq))
                enable = 1;
 
        if (enable) {
@@ -1054,8 +1105,7 @@ static void set_maintenance_mode(void *send_info, int enable)
                atomic_set(&smi_info->req_events, 0);
 }
 
-static struct ipmi_smi_handlers handlers =
-{
+static struct ipmi_smi_handlers handlers = {
        .owner                  = THIS_MODULE,
        .start_processing       = smi_start_processing,
        .sender                 = sender,
@@ -1065,8 +1115,10 @@ static struct ipmi_smi_handlers handlers =
        .poll                   = poll,
 };
 
-/* There can be 4 IO ports passed in (with or without IRQs), 4 addresses,
-   a default IO port, and 1 ACPI/SPMI address.  That sets SI_MAX_DRIVERS */
+/*
+ * There can be 4 IO ports passed in (with or without IRQs), 4 addresses,
+ * a default IO port, and 1 ACPI/SPMI address.  That sets SI_MAX_DRIVERS.
+ */
 
 static LIST_HEAD(smi_infos);
 static DEFINE_MUTEX(smi_infos_lock);
@@ -1257,10 +1309,9 @@ static void port_cleanup(struct smi_info *info)
        int          idx;
 
        if (addr) {
-               for (idx = 0; idx < info->io_size; idx++) {
+               for (idx = 0; idx < info->io_size; idx++)
                        release_region(addr + idx * info->io.regspacing,
                                       info->io.regsize);
-               }
        }
 }
 
@@ -1274,8 +1325,10 @@ static int port_setup(struct smi_info *info)
 
        info->io_cleanup = port_cleanup;
 
-       /* Figure out the actual inb/inw/inl/etc routine to use based
-          upon the register size. */
+       /*
+        * Figure out the actual inb/inw/inl/etc routine to use based
+        * upon the register size.
+        */
        switch (info->io.regsize) {
        case 1:
                info->io.inputb = port_inb;
@@ -1290,17 +1343,18 @@ static int port_setup(struct smi_info *info)
                info->io.outputb = port_outl;
                break;
        default:
-               printk("ipmi_si: Invalid register size: %d\n",
+               printk(KERN_WARNING "ipmi_si: Invalid register size: %d\n",
                       info->io.regsize);
                return -EINVAL;
        }
 
-       /* Some BIOSes reserve disjoint I/O regions in their ACPI
+       /*
+        * Some BIOSes reserve disjoint I/O regions in their ACPI
         * tables.  This causes problems when trying to register the
         * entire I/O region.  Therefore we must register each I/O
         * port separately.
         */
-       for (idx = 0; idx < info->io_size; idx++) {
+       for (idx = 0; idx < info->io_size; idx++) {
                if (request_region(addr + idx * info->io.regspacing,
                                   info->io.regsize, DEVICE_NAME) == NULL) {
                        /* Undo allocations */
@@ -1388,8 +1442,10 @@ static int mem_setup(struct smi_info *info)
 
        info->io_cleanup = mem_cleanup;
 
-       /* Figure out the actual readb/readw/readl/etc routine to use based
-          upon the register size. */
+       /*
+        * Figure out the actual readb/readw/readl/etc routine to use based
+        * upon the register size.
+        */
        switch (info->io.regsize) {
        case 1:
                info->io.inputb = intf_mem_inb;
@@ -1410,16 +1466,18 @@ static int mem_setup(struct smi_info *info)
                break;
 #endif
        default:
-               printk("ipmi_si: Invalid register size: %d\n",
+               printk(KERN_WARNING "ipmi_si: Invalid register size: %d\n",
                       info->io.regsize);
                return -EINVAL;
        }
 
-       /* Calculate the total amount of memory to claim.  This is an
+       /*
+        * Calculate the total amount of memory to claim.  This is an
         * unusual looking calculation, but it avoids claiming any
         * more memory than it has to.  It will claim everything
         * between the first address to the end of the last full
-        * register. */
+        * register.
+        */
        mapsize = ((info->io_size * info->io.regspacing)
                   - (info->io.regspacing - info->io.regsize));
 
@@ -1749,9 +1807,11 @@ static __devinit void hardcode_find_bmc(void)
 
 #include <linux/acpi.h>
 
-/* Once we get an ACPI failure, we don't try any more, because we go
-   through the tables sequentially.  Once we don't find a table, there
-   are no more. */
+/*
+ * Once we get an ACPI failure, we don't try any more, because we go
+ * through the tables sequentially.  Once we don't find a table, there
+ * are no more.
+ */
 static int acpi_failure;
 
 /* For GPE-type interrupts. */
@@ -1765,9 +1825,7 @@ static u32 ipmi_acpi_gpe(void *context)
 
        spin_lock_irqsave(&(smi_info->si_lock), flags);
 
-       spin_lock(&smi_info->count_lock);
-       smi_info->interrupts++;
-       spin_unlock(&smi_info->count_lock);
+       smi_inc_stat(smi_info, interrupts);
 
 #ifdef DEBUG_TIMING
        do_gettimeofday(&t);
@@ -1816,7 +1874,8 @@ static int acpi_gpe_irq_setup(struct smi_info *info)
 
 /*
  * Defined at
- * http://h21007.www2.hp.com/dspp/files/unprotected/devresource/Docs/TechPapers/IA64/hpspmi.pdf
+ * http://h21007.www2.hp.com/dspp/files/unprotected/devresource/
+ * Docs/TechPapers/IA64/hpspmi.pdf
  */
 struct SPMITable {
        s8      Signature[4];
@@ -1838,14 +1897,18 @@ struct SPMITable {
         */
        u8      InterruptType;
 
-       /* If bit 0 of InterruptType is set, then this is the SCI
-           interrupt in the GPEx_STS register. */
+       /*
+        * If bit 0 of InterruptType is set, then this is the SCI
+        * interrupt in the GPEx_STS register.
+        */
        u8      GPE;
 
        s16     Reserved;
 
-       /* If bit 1 of InterruptType is set, then this is the I/O
-           APIC/SAPIC interrupt. */
+       /*
+        * If bit 1 of InterruptType is set, then this is the I/O
+        * APIC/SAPIC interrupt.
+        */
        u32     GlobalSystemInterrupt;
 
        /* The actual register address. */
@@ -1863,7 +1926,7 @@ static __devinit int try_init_acpi(struct SPMITable *spmi)
 
        if (spmi->IPMIlegacy != 1) {
            printk(KERN_INFO "IPMI: Bad SPMI legacy %d\n", spmi->IPMIlegacy);
-           return -ENODEV;
+           return -ENODEV;
        }
 
        if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
@@ -1880,8 +1943,7 @@ static __devinit int try_init_acpi(struct SPMITable *spmi)
        info->addr_source = "ACPI";
 
        /* Figure out the interface type. */
-       switch (spmi->InterfaceType)
-       {
+       switch (spmi->InterfaceType) {
        case 1: /* KCS */
                info->si_type = SI_KCS;
                break;
@@ -1929,7 +1991,8 @@ static __devinit int try_init_acpi(struct SPMITable *spmi)
                info->io.addr_type = IPMI_IO_ADDR_SPACE;
        } else {
                kfree(info);
-               printk("ipmi_si: Unknown ACPI I/O Address type\n");
+               printk(KERN_WARNING
+                      "ipmi_si: Unknown ACPI I/O Address type\n");
                return -EIO;
        }
        info->io.addr_data = spmi->addr.address;
@@ -1963,8 +2026,7 @@ static __devinit void acpi_find_bmc(void)
 #endif
 
 #ifdef CONFIG_DMI
-struct dmi_ipmi_data
-{
+struct dmi_ipmi_data {
        u8              type;
        u8              addr_space;
        unsigned long   base_addr;
@@ -1989,11 +2051,10 @@ static int __devinit decode_dmi(const struct dmi_header *dm,
                        /* I/O */
                        base_addr &= 0xFFFE;
                        dmi->addr_space = IPMI_IO_ADDR_SPACE;
-               }
-               else {
+               } else
                        /* Memory */
                        dmi->addr_space = IPMI_MEM_ADDR_SPACE;
-               }
+
                /* If bit 4 of byte 0x10 is set, then the lsb for the address
                   is odd. */
                dmi->base_addr = base_addr | ((data[0x10] & 0x10) >> 4);
@@ -2002,7 +2063,7 @@ static int __devinit decode_dmi(const struct dmi_header *dm,
 
                /* The top two bits of byte 0x10 hold the register spacing. */
                reg_spacing = (data[0x10] & 0xC0) >> 6;
-               switch(reg_spacing){
+               switch (reg_spacing) {
                case 0x00: /* Byte boundaries */
                    dmi->offset = 1;
                    break;
@@ -2018,12 +2079,14 @@ static int __devinit decode_dmi(const struct dmi_header *dm,
                }
        } else {
                /* Old DMI spec. */
-               /* Note that technically, the lower bit of the base
+               /*
+                * Note that technically, the lower bit of the base
                 * address should be 1 if the address is I/O and 0 if
                 * the address is in memory.  So many systems get that
                 * wrong (and all that I have seen are I/O) so we just
                 * ignore that bit and assume I/O.  Systems that use
-                * memory should use the newer spec, anyway. */
+                * memory should use the newer spec, anyway.
+                */
                dmi->base_addr = base_addr & 0xfffe;
                dmi->addr_space = IPMI_IO_ADDR_SPACE;
                dmi->offset = 1;
@@ -2230,13 +2293,13 @@ static struct pci_device_id ipmi_pci_devices[] = {
 MODULE_DEVICE_TABLE(pci, ipmi_pci_devices);
 
 static struct pci_driver ipmi_pci_driver = {
-        .name =         DEVICE_NAME,
-        .id_table =     ipmi_pci_devices,
-        .probe =        ipmi_pci_probe,
-        .remove =       __devexit_p(ipmi_pci_remove),
+       .name =         DEVICE_NAME,
+       .id_table =     ipmi_pci_devices,
+       .probe =        ipmi_pci_probe,
+       .remove =       __devexit_p(ipmi_pci_remove),
 #ifdef CONFIG_PM
-        .suspend =      ipmi_pci_suspend,
-        .resume =       ipmi_pci_resume,
+       .suspend =      ipmi_pci_suspend,
+       .resume =       ipmi_pci_resume,
 #endif
 };
 #endif /* CONFIG_PCI */
@@ -2306,7 +2369,7 @@ static int __devinit ipmi_of_probe(struct of_device *dev,
                info->io.addr_data, info->io.regsize, info->io.regspacing,
                info->irq);
 
-       dev->dev.driver_data = (void*) info;
+       dev->dev.driver_data = (void *) info;
 
        return try_smi_init(info);
 }
@@ -2319,14 +2382,16 @@ static int __devexit ipmi_of_remove(struct of_device *dev)
 
 static struct of_device_id ipmi_match[] =
 {
-       { .type = "ipmi", .compatible = "ipmi-kcs",  .data = (void *)(unsigned long) SI_KCS },
-       { .type = "ipmi", .compatible = "ipmi-smic", .data = (void *)(unsigned long) SI_SMIC },
-       { .type = "ipmi", .compatible = "ipmi-bt",   .data = (void *)(unsigned long) SI_BT },
+       { .type = "ipmi", .compatible = "ipmi-kcs",
+         .data = (void *)(unsigned long) SI_KCS },
+       { .type = "ipmi", .compatible = "ipmi-smic",
+         .data = (void *)(unsigned long) SI_SMIC },
+       { .type = "ipmi", .compatible = "ipmi-bt",
+         .data = (void *)(unsigned long) SI_BT },
        {},
 };
 
-static struct of_platform_driver ipmi_of_platform_driver =
-{
+static struct of_platform_driver ipmi_of_platform_driver = {
        .name           = "ipmi",
        .match_table    = ipmi_match,
        .probe          = ipmi_of_probe,
@@ -2347,32 +2412,32 @@ static int try_get_dev_id(struct smi_info *smi_info)
        if (!resp)
                return -ENOMEM;
 
-       /* Do a Get Device ID command, since it comes back with some
-          useful info. */
+       /*
+        * Do a Get Device ID command, since it comes back with some
+        * useful info.
+        */
        msg[0] = IPMI_NETFN_APP_REQUEST << 2;
        msg[1] = IPMI_GET_DEVICE_ID_CMD;
        smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
 
        smi_result = smi_info->handlers->event(smi_info->si_sm, 0);
-       for (;;)
-       {
+       for (;;) {
                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);
-               }
-               else if (smi_result == SI_SM_CALL_WITHOUT_DELAY)
-               {
+               } else if (smi_result == SI_SM_CALL_WITHOUT_DELAY) {
                        smi_result = smi_info->handlers->event(
                                smi_info->si_sm, 0);
-               }
-               else
+               } else
                        break;
        }
        if (smi_result == SI_SM_HOSED) {
-               /* We couldn't get the state machine to run, so whatever's at
-                  the port is probably not an IPMI SMI interface. */
+               /*
+                * We couldn't get the state machine to run, so whatever's at
+                * the port is probably not an IPMI SMI interface.
+                */
                rv = -ENODEV;
                goto out;
        }
@@ -2405,30 +2470,28 @@ static int stat_file_read_proc(char *page, char **start, off_t off,
 
        out += sprintf(out, "interrupts_enabled:    %d\n",
                       smi->irq && !smi->interrupt_disabled);
-       out += sprintf(out, "short_timeouts:        %ld\n",
-                      smi->short_timeouts);
-       out += sprintf(out, "long_timeouts:         %ld\n",
-                      smi->long_timeouts);
-       out += sprintf(out, "timeout_restarts:      %ld\n",
-                      smi->timeout_restarts);
-       out += sprintf(out, "idles:                 %ld\n",
-                      smi->idles);
-       out += sprintf(out, "interrupts:            %ld\n",
-                      smi->interrupts);
-       out += sprintf(out, "attentions:            %ld\n",
-                      smi->attentions);
-       out += sprintf(out, "flag_fetches:          %ld\n",
-                      smi->flag_fetches);
-       out += sprintf(out, "hosed_count:           %ld\n",
-                      smi->hosed_count);
-       out += sprintf(out, "complete_transactions: %ld\n",
-                      smi->complete_transactions);
-       out += sprintf(out, "events:                %ld\n",
-                      smi->events);
-       out += sprintf(out, "watchdog_pretimeouts:  %ld\n",
-                      smi->watchdog_pretimeouts);
-       out += sprintf(out, "incoming_messages:     %ld\n",
-                      smi->incoming_messages);
+       out += sprintf(out, "short_timeouts:        %u\n",
+                      smi_get_stat(smi, short_timeouts));
+       out += sprintf(out, "long_timeouts:         %u\n",
+                      smi_get_stat(smi, long_timeouts));
+       out += sprintf(out, "idles:                 %u\n",
+                      smi_get_stat(smi, idles));
+       out += sprintf(out, "interrupts:            %u\n",
+                      smi_get_stat(smi, interrupts));
+       out += sprintf(out, "attentions:            %u\n",
+                      smi_get_stat(smi, attentions));
+       out += sprintf(out, "flag_fetches:          %u\n",
+                      smi_get_stat(smi, flag_fetches));
+       out += sprintf(out, "hosed_count:           %u\n",
+                      smi_get_stat(smi, hosed_count));
+       out += sprintf(out, "complete_transactions: %u\n",
+                      smi_get_stat(smi, complete_transactions));
+       out += sprintf(out, "events:                %u\n",
+                      smi_get_stat(smi, events));
+       out += sprintf(out, "watchdog_pretimeouts:  %u\n",
+                      smi_get_stat(smi, watchdog_pretimeouts));
+       out += sprintf(out, "incoming_messages:     %u\n",
+                      smi_get_stat(smi, incoming_messages));
 
        return out - page;
 }
@@ -2460,7 +2523,7 @@ static int param_read_proc(char *page, char **start, off_t off,
 static int oem_data_avail_to_receive_msg_avail(struct smi_info *smi_info)
 {
        smi_info->msg_flags = ((smi_info->msg_flags & ~OEM_DATA_AVAIL) |
-                               RECEIVE_MSG_AVAIL);
+                              RECEIVE_MSG_AVAIL);
        return 1;
 }
 
@@ -2502,10 +2565,9 @@ static void setup_dell_poweredge_oem_data_handler(struct smi_info *smi_info)
                    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)) {
+               } 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;
                }
@@ -2597,8 +2659,10 @@ static void setup_xaction_handlers(struct smi_info *smi_info)
 static inline void wait_for_timer_and_thread(struct smi_info *smi_info)
 {
        if (smi_info->intf) {
-               /* The timer and thread are only running if the
-                  interface has been started up and registered. */
+               /*
+                * The timer and thread are only running if the
+                * interface has been started up and registered.
+                */
                if (smi_info->thread != NULL)
                        kthread_stop(smi_info->thread);
                del_timer_sync(&smi_info->si_timer);
@@ -2676,6 +2740,7 @@ static int is_new_interface(struct smi_info *info)
 static int try_smi_init(struct smi_info *new_smi)
 {
        int rv;
+       int i;
 
        if (new_smi->addr_source) {
                printk(KERN_INFO "ipmi_si: Trying %s-specified %s state"
@@ -2722,7 +2787,7 @@ static int try_smi_init(struct smi_info *new_smi)
        /* Allocate the state machine's data and initialize it. */
        new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL);
        if (!new_smi->si_sm) {
-               printk(Could not allocate state machine memory\n");
+               printk(KERN_ERR "Could not allocate state machine memory\n");
                rv = -ENOMEM;
                goto out_err;
        }
@@ -2732,13 +2797,12 @@ static int try_smi_init(struct smi_info *new_smi)
        /* Now that we know the I/O size, we can set up the I/O. */
        rv = new_smi->io_setup(new_smi);
        if (rv) {
-               printk(Could not set up I/O space\n");
+               printk(KERN_ERR "Could not set up I/O space\n");
                goto out_err;
        }
 
        spin_lock_init(&(new_smi->si_lock));
        spin_lock_init(&(new_smi->msg_lock));
-       spin_lock_init(&(new_smi->count_lock));
 
        /* Do low-level detection first. */
        if (new_smi->handlers->detect(new_smi->si_sm)) {
@@ -2749,8 +2813,10 @@ static int try_smi_init(struct smi_info *new_smi)
                goto out_err;
        }
 
-       /* Attempt a get device id command.  If it fails, we probably
-           don't have a BMC here. */
+       /*
+        * Attempt a get device id command.  If it fails, we probably
+        * don't have a BMC here.
+        */
        rv = try_get_dev_id(new_smi);
        if (rv) {
                if (new_smi->addr_source)
@@ -2767,22 +2833,28 @@ static int try_smi_init(struct smi_info *new_smi)
        new_smi->curr_msg = NULL;
        atomic_set(&new_smi->req_events, 0);
        new_smi->run_to_completion = 0;
+       for (i = 0; i < SI_NUM_STATS; i++)
+               atomic_set(&new_smi->stats[i], 0);
 
        new_smi->interrupt_disabled = 0;
        atomic_set(&new_smi->stop_operation, 0);
        new_smi->intf_num = smi_num;
        smi_num++;
 
-       /* Start clearing the flags before we enable interrupts or the
-          timer to avoid racing with the timer. */
+       /*
+        * Start clearing the flags before we enable interrupts or the
+        * timer to avoid racing with the timer.
+        */
        start_clear_flags(new_smi);
        /* IRQ is defined to be set when non-zero. */
        if (new_smi->irq)
                new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ;
 
        if (!new_smi->dev) {
-               /* If we don't already have a device from something
-                * else (like PCI), then register a new one. */
+               /*
+                * If we don't already have a device from something
+                * else (like PCI), then register a new one.
+                */
                new_smi->pdev = platform_device_alloc("ipmi_si",
                                                      new_smi->intf_num);
                if (rv) {
@@ -2820,7 +2892,7 @@ static int try_smi_init(struct smi_info *new_smi)
        }
 
        rv = ipmi_smi_add_proc_entry(new_smi->intf, "type",
-                                    type_file_read_proc, NULL,
+                                    type_file_read_proc,
                                     new_smi, THIS_MODULE);
        if (rv) {
                printk(KERN_ERR
@@ -2830,7 +2902,7 @@ static int try_smi_init(struct smi_info *new_smi)
        }
 
        rv = ipmi_smi_add_proc_entry(new_smi->intf, "si_stats",
-                                    stat_file_read_proc, NULL,
+                                    stat_file_read_proc,
                                     new_smi, THIS_MODULE);
        if (rv) {
                printk(KERN_ERR
@@ -2840,7 +2912,7 @@ static int try_smi_init(struct smi_info *new_smi)
        }
 
        rv = ipmi_smi_add_proc_entry(new_smi->intf, "params",
-                                    param_read_proc, NULL,
+                                    param_read_proc,
                                     new_smi, THIS_MODULE);
        if (rv) {
                printk(KERN_ERR
@@ -2853,7 +2925,8 @@ static int try_smi_init(struct smi_info *new_smi)
 
        mutex_unlock(&smi_infos_lock);
 
-       printk(KERN_INFO "IPMI %s interface initialized\n",si_to_str[new_smi->si_type]);
+       printk(KERN_INFO "IPMI %s interface initialized\n",
+              si_to_str[new_smi->si_type]);
 
        return 0;
 
@@ -2868,9 +2941,11 @@ static int try_smi_init(struct smi_info *new_smi)
        if (new_smi->irq_cleanup)
                new_smi->irq_cleanup(new_smi);
 
-       /* Wait until we know that we are out of any interrupt
-          handlers might have been running before we freed the
-          interrupt. */
+       /*
+        * Wait until we know that we are out of any interrupt
+        * handlers might have been running before we freed the
+        * interrupt.
+        */
        synchronize_sched();
 
        if (new_smi->si_sm) {
@@ -2942,11 +3017,10 @@ static __devinit int init_ipmi_si(void)
 
 #ifdef CONFIG_PCI
        rv = pci_register_driver(&ipmi_pci_driver);
-       if (rv){
+       if (rv)
                printk(KERN_ERR
                       "init_ipmi_si: Unable to register PCI driver: %d\n",
                       rv);
-       }
 #endif
 
 #ifdef CONFIG_PPC_OF
@@ -2975,7 +3049,8 @@ static __devinit int init_ipmi_si(void)
                of_unregister_platform_driver(&ipmi_of_platform_driver);
 #endif
                driver_unregister(&ipmi_driver);
-               printk("ipmi_si: Unable to find any System Interface(s)\n");
+               printk(KERN_WARNING
+                      "ipmi_si: Unable to find any System Interface(s)\n");
                return -ENODEV;
        } else {
                mutex_unlock(&smi_infos_lock);
@@ -2997,13 +3072,17 @@ static void cleanup_one_si(struct smi_info *to_clean)
        /* Tell the driver that we are shutting down. */
        atomic_inc(&to_clean->stop_operation);
 
-       /* Make sure the timer and thread are stopped and will not run
-          again. */
+       /*
+        * Make sure the timer and thread are stopped and will not run
+        * again.
+        */
        wait_for_timer_and_thread(to_clean);
 
-       /* Timeouts are stopped, now make sure the interrupts are off
-          for the device.  A little tricky with locks to make sure
-          there are no races. */
+       /*
+        * Timeouts are stopped, now make sure the interrupts are off
+        * for the device.  A little tricky with locks to make sure
+        * there are no races.
+        */
        spin_lock_irqsave(&to_clean->si_lock, flags);
        while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) {
                spin_unlock_irqrestore(&to_clean->si_lock, flags);
@@ -3074,4 +3153,5 @@ module_exit(cleanup_ipmi_si);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
-MODULE_DESCRIPTION("Interface to the IPMI driver for the KCS, SMIC, and BT system interfaces.");
+MODULE_DESCRIPTION("Interface to the IPMI driver for the KCS, SMIC, and BT"
+                  " system interfaces.");
index 4b731b24dc16c79d2e688edafe9ac20837f60e45..df89f73475fb996770bfeae8f3710038feabb825 100644 (file)
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-/* This is defined by the state machines themselves, it is an opaque
-   data type for them to use. */
+/*
+ * This is defined by the state machines themselves, it is an opaque
+ * data type for them to use.
+ */
 struct si_sm_data;
 
-/* The structure for doing I/O in the state machine.  The state
-   machine doesn't have the actual I/O routines, they are done through
-   this interface. */
-struct si_sm_io
-{
+/*
+ * The structure for doing I/O in the state machine.  The state
+ * machine doesn't have the actual I/O routines, they are done through
+ * this interface.
+ */
+struct si_sm_io {
        unsigned char (*inputb)(struct si_sm_io *io, unsigned int offset);
        void (*outputb)(struct si_sm_io *io,
                        unsigned int  offset,
                        unsigned char b);
 
-       /* Generic info used by the actual handling routines, the
-           state machine shouldn't touch these. */
+       /*
+        * Generic info used by the actual handling routines, the
+        * state machine shouldn't touch these.
+        */
        void __iomem *addr;
        int  regspacing;
        int  regsize;
@@ -59,53 +64,67 @@ struct si_sm_io
 };
 
 /* Results of SMI events. */
-enum si_sm_result
-{
+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_CALL_WITH_TICK_DELAY,/* Delay >=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. */
-       SI_SM_ATTN              /* The hardware is asserting attn and the
-                                  state machine is idle. */
+
+       /*
+        * The hardware is asserting attn and the state machine is
+        * idle.
+        */
+       SI_SM_ATTN
 };
 
 /* Handlers for the SMI state machine. */
-struct si_sm_handlers
-{
-       /* Put the version number of the state machine here so the
-           upper layer can print it. */
+struct si_sm_handlers {
+       /*
+        * Put the version number of the state machine here so the
+        * upper layer can print it.
+        */
        char *version;
 
-       /* Initialize the data and return the amount of I/O space to
-           reserve for the space. */
+       /*
+        * Initialize the data and return the amount of I/O space to
+        * reserve for the space.
+        */
        unsigned int (*init_data)(struct si_sm_data *smi,
                                  struct si_sm_io   *io);
 
-       /* Start a new transaction in the state machine.  This will
-          return -2 if the state machine is not idle, -1 if the size
-          is invalid (to large or too small), or 0 if the transaction
-          is successfully completed. */
+       /*
+        * Start a new transaction in the state machine.  This will
+        * return -2 if the state machine is not idle, -1 if the size
+        * is invalid (to large or too small), or 0 if the transaction
+        * is successfully completed.
+        */
        int (*start_transaction)(struct si_sm_data *smi,
                                 unsigned char *data, unsigned int size);
 
-       /* Return the results after the transaction.  This will return
-          -1 if the buffer is too small, zero if no transaction is
-          present, or the actual length of the result data. */
+       /*
+        * Return the results after the transaction.  This will return
+        * -1 if the buffer is too small, zero if no transaction is
+        * present, or the actual length of the result data.
+        */
        int (*get_result)(struct si_sm_data *smi,
                          unsigned char *data, unsigned int length);
 
-       /* Call this periodically (for a polled interface) or upon
-          receiving an interrupt (for a interrupt-driven interface).
-          If interrupt driven, you should probably poll this
-          periodically when not in idle state.  This should be called
-          with the time that passed since the last call, if it is
-          significant.  Time is in microseconds. */
+       /*
+        * Call this periodically (for a polled interface) or upon
+        * receiving an interrupt (for a interrupt-driven interface).
+        * If interrupt driven, you should probably poll this
+        * periodically when not in idle state.  This should be called
+        * with the time that passed since the last call, if it is
+        * significant.  Time is in microseconds.
+        */
        enum si_sm_result (*event)(struct si_sm_data *smi, long time);
 
-       /* Attempt to detect an SMI.  Returns 0 on success or nonzero
-           on failure. */
+       /*
+        * Attempt to detect an SMI.  Returns 0 on success or nonzero
+        * on failure.
+        */
        int (*detect)(struct si_sm_data *smi);
 
        /* The interface is shutting down, so clean it up. */
index e64ea7d25d241d858d7a3022e070de8952a4fc00..faed92971907212c24f2765b6d2f633fb0a5719a 100644 (file)
@@ -85,6 +85,7 @@ enum smic_states {
 /* 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
@@ -104,23 +105,22 @@ enum smic_states {
 #define        EC_ILLEGAL_COMMAND      0x04
 #define        EC_BUFFER_FULL          0x05
 
-struct si_sm_data
-{
+struct si_sm_data {
        enum smic_states state;
        struct si_sm_io *io;
-        unsigned char   write_data[MAX_SMIC_WRITE_SIZE];
-        int             write_pos;
-        int             write_count;
-        int             orig_write_count;
-        unsigned char   read_data[MAX_SMIC_READ_SIZE];
-        int             read_pos;
-        int             truncated;
-        unsigned int    error_retries;
-        long            smic_timeout;
+       unsigned char    write_data[MAX_SMIC_WRITE_SIZE];
+       int              write_pos;
+       int              write_count;
+       int              orig_write_count;
+       unsigned char    read_data[MAX_SMIC_READ_SIZE];
+       int              read_pos;
+       int              truncated;
+       unsigned int     error_retries;
+       long             smic_timeout;
 };
 
-static unsigned int init_smic_data (struct si_sm_data *smic,
-                                   struct si_sm_io *io)
+static unsigned int init_smic_data(struct si_sm_data *smic,
+                                  struct si_sm_io *io)
 {
        smic->state = SMIC_IDLE;
        smic->io = io;
@@ -150,11 +150,10 @@ static int start_smic_transaction(struct si_sm_data *smic,
                return IPMI_NOT_IN_MY_STATE_ERR;
 
        if (smic_debug & SMIC_DEBUG_MSG) {
-               printk(KERN_INFO "start_smic_transaction -");
-               for (i = 0; i < size; i ++) {
-                       printk (" %02x", (unsigned char) (data [i]));
-               }
-               printk ("\n");
+               printk(KERN_DEBUG "start_smic_transaction -");
+               for (i = 0; i < size; i++)
+                       printk(" %02x", (unsigned char) data[i]);
+               printk("\n");
        }
        smic->error_retries = 0;
        memcpy(smic->write_data, data, size);
@@ -173,11 +172,10 @@ static int smic_get_result(struct si_sm_data *smic,
        int i;
 
        if (smic_debug & SMIC_DEBUG_MSG) {
-               printk (KERN_INFO "smic_get result -");
-               for (i = 0; i < smic->read_pos; i ++) {
-                       printk (" %02x", (smic->read_data [i]));
-               }
-               printk ("\n");
+               printk(KERN_DEBUG "smic_get result -");
+               for (i = 0; i < smic->read_pos; i++)
+                       printk(" %02x", smic->read_data[i]);
+               printk("\n");
        }
        if (length < smic->read_pos) {
                smic->read_pos = length;
@@ -223,8 +221,8 @@ static inline void write_smic_control(struct si_sm_data *smic,
        smic->io->outputb(smic->io, 1, control);
 }
 
-static inline void write_si_sm_data (struct si_sm_data *smic,
-                                  unsigned char   data)
+static inline void write_si_sm_data(struct si_sm_data *smic,
+                                   unsigned char   data)
 {
        smic->io->outputb(smic->io, 0, data);
 }
@@ -233,10 +231,9 @@ static inline void start_error_recovery(struct si_sm_data *smic, char *reason)
 {
        (smic->error_retries)++;
        if (smic->error_retries > SMIC_MAX_ERROR_RETRIES) {
-               if (smic_debug & SMIC_DEBUG_ENABLE) {
+               if (smic_debug & SMIC_DEBUG_ENABLE)
                        printk(KERN_WARNING
                               "ipmi_smic_drv: smic hosed: %s\n", reason);
-               }
                smic->state = SMIC_HOSED;
        } else {
                smic->write_count = smic->orig_write_count;
@@ -254,14 +251,14 @@ static inline void write_next_byte(struct si_sm_data *smic)
        (smic->write_count)--;
 }
 
-static inline void read_next_byte (struct si_sm_data *smic)
+static inline void read_next_byte(struct si_sm_data *smic)
 {
        if (smic->read_pos >= MAX_SMIC_READ_SIZE) {
-               read_smic_data (smic);
+               read_smic_data(smic);
                smic->truncated = 1;
        } else {
                smic->read_data[smic->read_pos] = read_smic_data(smic);
-               (smic->read_pos)++;
+               smic->read_pos++;
        }
 }
 
@@ -336,7 +333,7 @@ static inline void read_next_byte (struct si_sm_data *smic)
        SMIC_SC_SMS_RD_END      0xC6
 */
 
-static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
+static enum si_sm_result smic_event(struct si_sm_data *smic, long time)
 {
        unsigned char status;
        unsigned char flags;
@@ -347,13 +344,15 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
                return SI_SM_HOSED;
        }
        if (smic->state != SMIC_IDLE) {
-               if (smic_debug & SMIC_DEBUG_STATES) {
-                       printk(KERN_INFO
+               if (smic_debug & SMIC_DEBUG_STATES)
+                       printk(KERN_DEBUG
                               "smic_event - smic->smic_timeout = %ld,"
                               " time = %ld\n",
                               smic->smic_timeout, time);
-               }
-/* FIXME: smic_event is sometimes called with time > SMIC_RETRY_TIMEOUT */
+               /*
+                * FIXME: smic_event is sometimes called with time >
+                * SMIC_RETRY_TIMEOUT
+                */
                if (time < SMIC_RETRY_TIMEOUT) {
                        smic->smic_timeout -= time;
                        if (smic->smic_timeout < 0) {
@@ -366,9 +365,9 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
        if (flags & SMIC_FLAG_BSY)
                return SI_SM_CALL_WITH_DELAY;
 
-       status = read_smic_status (smic);
+       status = read_smic_status(smic);
        if (smic_debug & SMIC_DEBUG_STATES)
-               printk(KERN_INFO
+               printk(KERN_DEBUG
                       "smic_event - state = %d, flags = 0x%02x,"
                       " status = 0x%02x\n",
                       smic->state, flags, status);
@@ -377,9 +376,7 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
        case SMIC_IDLE:
                /* in IDLE we check for available messages */
                if (flags & SMIC_SMS_DATA_AVAIL)
-               {
                        return SI_SM_ATTN;
-               }
                return SI_SM_IDLE;
 
        case SMIC_START_OP:
@@ -391,7 +388,7 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
 
        case SMIC_OP_OK:
                if (status != SMIC_SC_SMS_READY) {
-                               /* this should not happen */
+                       /* this should not happen */
                        start_error_recovery(smic,
                                             "state = SMIC_OP_OK,"
                                             " status != SMIC_SC_SMS_READY");
@@ -411,8 +408,10 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
                                             "status != SMIC_SC_SMS_WR_START");
                        return SI_SM_CALL_WITH_DELAY;
                }
-               /* we must not issue WR_(NEXT|END) unless
-                   TX_DATA_READY is set */
+               /*
+                * we must not issue WR_(NEXT|END) unless
+                * TX_DATA_READY is set
+                * */
                if (flags & SMIC_TX_DATA_READY) {
                        if (smic->write_count == 1) {
                                /* last byte */
@@ -424,10 +423,8 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
                        }
                        write_next_byte(smic);
                        write_smic_flags(smic, flags | SMIC_FLAG_BSY);
-               }
-               else {
+               } else
                        return SI_SM_CALL_WITH_DELAY;
-               }
                break;
 
        case SMIC_WRITE_NEXT:
@@ -442,52 +439,48 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
                        if (smic->write_count == 1) {
                                write_smic_control(smic, SMIC_CC_SMS_WR_END);
                                smic->state = SMIC_WRITE_END;
-                       }
-                       else {
+                       } else {
                                write_smic_control(smic, SMIC_CC_SMS_WR_NEXT);
                                smic->state = SMIC_WRITE_NEXT;
                        }
                        write_next_byte(smic);
                        write_smic_flags(smic, flags | SMIC_FLAG_BSY);
-               }
-               else {
+               } else
                        return SI_SM_CALL_WITH_DELAY;
-               }
                break;
 
        case SMIC_WRITE_END:
                if (status != SMIC_SC_SMS_WR_END) {
-                       start_error_recovery (smic,
-                                             "state = SMIC_WRITE_END, "
-                                             "status != SMIC_SC_SMS_WR_END");
+                       start_error_recovery(smic,
+                                            "state = SMIC_WRITE_END, "
+                                            "status != SMIC_SC_SMS_WR_END");
                        return SI_SM_CALL_WITH_DELAY;
                }
                /* data register holds an error code */
                data = read_smic_data(smic);
                if (data != 0) {
-                       if (smic_debug & SMIC_DEBUG_ENABLE) {
-                               printk(KERN_INFO
+                       if (smic_debug & SMIC_DEBUG_ENABLE)
+                               printk(KERN_DEBUG
                                       "SMIC_WRITE_END: data = %02x\n", data);
-                       }
                        start_error_recovery(smic,
                                             "state = SMIC_WRITE_END, "
                                             "data != SUCCESS");
                        return SI_SM_CALL_WITH_DELAY;
-               } else {
+               } else
                        smic->state = SMIC_WRITE2READ;
-               }
                break;
 
        case SMIC_WRITE2READ:
-               /* we must wait for RX_DATA_READY to be set before we
-                   can continue */
+               /*
+                * we must wait for RX_DATA_READY to be set before we
+                * can continue
+                */
                if (flags & SMIC_RX_DATA_READY) {
                        write_smic_control(smic, SMIC_CC_SMS_RD_START);
                        write_smic_flags(smic, flags | SMIC_FLAG_BSY);
                        smic->state = SMIC_READ_START;
-               } else {
+               } else
                        return SI_SM_CALL_WITH_DELAY;
-               }
                break;
 
        case SMIC_READ_START:
@@ -502,15 +495,16 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
                        write_smic_control(smic, SMIC_CC_SMS_RD_NEXT);
                        write_smic_flags(smic, flags | SMIC_FLAG_BSY);
                        smic->state = SMIC_READ_NEXT;
-               } else {
+               } else
                        return SI_SM_CALL_WITH_DELAY;
-               }
                break;
 
        case SMIC_READ_NEXT:
                switch (status) {
-               /* smic tells us that this is the last byte to be read
-                   --> clean up */
+               /*
+                * smic tells us that this is the last byte to be read
+                * --> clean up
+                */
                case SMIC_SC_SMS_RD_END:
                        read_next_byte(smic);
                        write_smic_control(smic, SMIC_CC_SMS_RD_END);
@@ -523,9 +517,8 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
                                write_smic_control(smic, SMIC_CC_SMS_RD_NEXT);
                                write_smic_flags(smic, flags | SMIC_FLAG_BSY);
                                smic->state = SMIC_READ_NEXT;
-                       } else {
+                       } else
                                return SI_SM_CALL_WITH_DELAY;
-                       }
                        break;
                default:
                        start_error_recovery(
@@ -546,10 +539,9 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
                data = read_smic_data(smic);
                /* data register holds an error code */
                if (data != 0) {
-                       if (smic_debug & SMIC_DEBUG_ENABLE) {
-                               printk(KERN_INFO
+                       if (smic_debug & SMIC_DEBUG_ENABLE)
+                               printk(KERN_DEBUG
                                       "SMIC_READ_END: data = %02x\n", data);
-                       }
                        start_error_recovery(smic,
                                             "state = SMIC_READ_END, "
                                             "data != SUCCESS");
@@ -565,7 +557,7 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
 
        default:
                if (smic_debug & SMIC_DEBUG_ENABLE) {
-                       printk(KERN_WARNING "smic->state = %d\n", smic->state);
+                       printk(KERN_DEBUG "smic->state = %d\n", smic->state);
                        start_error_recovery(smic, "state = UNKNOWN");
                        return SI_SM_CALL_WITH_DELAY;
                }
@@ -576,10 +568,12 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
 
 static int smic_detect(struct si_sm_data *smic)
 {
-       /* It's impossible for the SMIC fnags register to be all 1's,
-          (assuming a properly functioning, self-initialized BMC)
-          but that's what you get from reading a bogus address, so we
-          test that first. */
+       /*
+        * It's impossible for the SMIC fnags register to be all 1's,
+        * (assuming a properly functioning, self-initialized BMC)
+        * but that's what you get from reading a bogus address, so we
+        * test that first.
+        */
        if (read_smic_flags(smic) == 0xff)
                return 1;
 
@@ -595,8 +589,7 @@ static int smic_size(void)
        return sizeof(struct si_sm_data);
 }
 
-struct si_sm_handlers smic_smi_handlers =
-{
+struct si_sm_handlers smic_smi_handlers = {
        .init_data         = init_smic_data,
        .start_transaction = start_smic_transaction,
        .get_result        = smic_get_result,
index 8f45ca9235ad10fb41ece3d803d776843bb3ea53..1b9a8704781783d6e9f9f8416cc9ef6e07c280c6 100644 (file)
 #include <asm/atomic.h>
 
 #ifdef CONFIG_X86
-/* This is ugly, but I've determined that x86 is the only architecture
-   that can reasonably support the IPMI NMI watchdog timeout at this
-   time.  If another architecture adds this capability somehow, it
-   will have to be a somewhat different mechanism and I have no idea
-   how it will work.  So in the unlikely event that another
-   architecture supports this, we can figure out a good generic
-   mechanism for it at that time. */
+/*
+ * This is ugly, but I've determined that x86 is the only architecture
+ * that can reasonably support the IPMI NMI watchdog timeout at this
+ * time.  If another architecture adds this capability somehow, it
+ * will have to be a somewhat different mechanism and I have no idea
+ * how it will work.  So in the unlikely event that another
+ * architecture supports this, we can figure out a good generic
+ * mechanism for it at that time.
+ */
 #include <asm/kdebug.h>
 #define HAVE_DIE_NMI
 #endif
@@ -95,9 +97,8 @@
 /* Operations that can be performed on a pretimout. */
 #define WDOG_PREOP_NONE                0
 #define WDOG_PREOP_PANIC       1
-#define WDOG_PREOP_GIVE_DATA   2 /* Cause data to be available to
-                                     read.  Doesn't work in NMI
-                                     mode. */
+/* Cause data to be available to read.  Doesn't work in NMI mode. */
+#define WDOG_PREOP_GIVE_DATA   2
 
 /* Actions to perform on a full timeout. */
 #define WDOG_SET_TIMEOUT_ACT(byte, use) \
 #define WDOG_TIMEOUT_POWER_DOWN                2
 #define WDOG_TIMEOUT_POWER_CYCLE       3
 
-/* Byte 3 of the get command, byte 4 of the get response is the
-   pre-timeout in seconds. */
+/*
+ * Byte 3 of the get command, byte 4 of the get response is the
+ * pre-timeout in seconds.
+ */
 
 /* Bits for setting byte 4 of the set command, byte 5 of the get response. */
 #define WDOG_EXPIRE_CLEAR_BIOS_FRB2    (1 << 1)
 #define WDOG_EXPIRE_CLEAR_SMS_OS       (1 << 4)
 #define WDOG_EXPIRE_CLEAR_OEM          (1 << 5)
 
-/* Setting/getting the watchdog timer value.  This is for bytes 5 and
-   6 (the timeout time) of the set command, and bytes 6 and 7 (the
-   timeout time) and 8 and 9 (the current countdown value) of the
-   response.  The timeout value is given in seconds (in the command it
-   is 100ms intervals). */
+/*
+ * Setting/getting the watchdog timer value.  This is for bytes 5 and
+ * 6 (the timeout time) of the set command, and bytes 6 and 7 (the
+ * timeout time) and 8 and 9 (the current countdown value) of the
+ * response.  The timeout value is given in seconds (in the command it
+ * is 100ms intervals).
+ */
 #define WDOG_SET_TIMEOUT(byte1, byte2, val) \
        (byte1) = (((val) * 10) & 0xff), (byte2) = (((val) * 10) >> 8)
 #define WDOG_GET_TIMEOUT(byte1, byte2) \
@@ -184,8 +189,10 @@ static int ipmi_set_timeout(int do_heartbeat);
 static void ipmi_register_watchdog(int ipmi_intf);
 static void ipmi_unregister_watchdog(int ipmi_intf);
 
-/* If true, the driver will start running as soon as it is configured
-   and ready. */
+/*
+ * If true, the driver will start running as soon as it is configured
+ * and ready.
+ */
 static int start_now;
 
 static int set_param_int(const char *val, struct kernel_param *kp)
@@ -309,10 +316,12 @@ static int ipmi_ignore_heartbeat;
 /* Is someone using the watchdog?  Only one user is allowed. */
 static unsigned long ipmi_wdog_open;
 
-/* If set to 1, the heartbeat command will set the state to reset and
-   start the timer.  The timer doesn't normally run when the driver is
-   first opened until the heartbeat is set the first time, this
-   variable is used to accomplish this. */
+/*
+ * If set to 1, the heartbeat command will set the state to reset and
+ * start the timer.  The timer doesn't normally run when the driver is
+ * first opened until the heartbeat is set the first time, this
+ * variable is used to accomplish this.
+ */
 static int ipmi_start_timer_on_heartbeat;
 
 /* IPMI version of the BMC. */
@@ -329,10 +338,12 @@ static int nmi_handler_registered;
 
 static int ipmi_heartbeat(void);
 
-/* We use a mutex to make sure that only one thing can send a set
-   timeout at one time, because we only have one copy of the data.
-   The mutex is claimed when the set_timeout is sent and freed
-   when both messages are free. */
+/*
+ * We use a mutex to make sure that only one thing can send a set
+ * timeout at one time, because we only have one copy of the data.
+ * The mutex is claimed when the set_timeout is sent and freed
+ * when both messages are free.
+ */
 static atomic_t set_timeout_tofree = ATOMIC_INIT(0);
 static DEFINE_MUTEX(set_timeout_lock);
 static DECLARE_COMPLETION(set_timeout_wait);
@@ -346,15 +357,13 @@ static void set_timeout_free_recv(struct ipmi_recv_msg *msg)
     if (atomic_dec_and_test(&set_timeout_tofree))
            complete(&set_timeout_wait);
 }
-static struct ipmi_smi_msg set_timeout_smi_msg =
-{
+static struct ipmi_smi_msg set_timeout_smi_msg = {
        .done = set_timeout_free_smi
 };
-static struct ipmi_recv_msg set_timeout_recv_msg =
-{
+static struct ipmi_recv_msg set_timeout_recv_msg = {
        .done = set_timeout_free_recv
 };
+
 static int i_ipmi_set_timeout(struct ipmi_smi_msg  *smi_msg,
                              struct ipmi_recv_msg *recv_msg,
                              int                  *send_heartbeat_now)
@@ -373,13 +382,14 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg  *smi_msg,
        WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS);
 
        if ((ipmi_version_major > 1)
-           || ((ipmi_version_major == 1) && (ipmi_version_minor >= 5)))
-       {
+           || ((ipmi_version_major == 1) && (ipmi_version_minor >= 5))) {
                /* This is an IPMI 1.5-only feature. */
                data[0] |= WDOG_DONT_STOP_ON_SET;
        } else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
-               /* In ipmi 1.0, setting the timer stops the watchdog, we
-                  need to start it back up again. */
+               /*
+                * In ipmi 1.0, setting the timer stops the watchdog, we
+                * need to start it back up again.
+                */
                hbnow = 1;
        }
 
@@ -465,12 +475,10 @@ static void panic_recv_free(struct ipmi_recv_msg *msg)
        atomic_dec(&panic_done_count);
 }
 
-static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg =
-{
+static struct ipmi_smi_msg panic_halt_heartbeat_smi_msg = {
        .done = panic_smi_free
 };
-static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg =
-{
+static struct ipmi_recv_msg panic_halt_heartbeat_recv_msg = {
        .done = panic_recv_free
 };
 
@@ -480,8 +488,10 @@ static void panic_halt_ipmi_heartbeat(void)
        struct ipmi_system_interface_addr addr;
        int rv;
 
-       /* Don't reset the timer if we have the timer turned off, that
-           re-enables the watchdog. */
+       /*
+        * Don't reset the timer if we have the timer turned off, that
+        * re-enables the watchdog.
+        */
        if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
                return;
 
@@ -505,19 +515,19 @@ static void panic_halt_ipmi_heartbeat(void)
                atomic_add(2, &panic_done_count);
 }
 
-static struct ipmi_smi_msg panic_halt_smi_msg =
-{
+static struct ipmi_smi_msg panic_halt_smi_msg = {
        .done = panic_smi_free
 };
-static struct ipmi_recv_msg panic_halt_recv_msg =
-{
+static struct ipmi_recv_msg panic_halt_recv_msg = {
        .done = panic_recv_free
 };
 
-/* Special call, doesn't claim any locks.  This is only to be called
-   at panic or halt time, in run-to-completion mode, when the caller
-   is the only CPU and the only thing that will be going is these IPMI
-   calls. */
+/*
+ * Special call, doesn't claim any locks.  This is only to be called
+ * at panic or halt time, in run-to-completion mode, when the caller
+ * is the only CPU and the only thing that will be going is these IPMI
+ * calls.
+ */
 static void panic_halt_ipmi_set_timeout(void)
 {
        int send_heartbeat_now;
@@ -540,10 +550,12 @@ static void panic_halt_ipmi_set_timeout(void)
                ipmi_poll_interface(watchdog_user);
 }
 
-/* We use a semaphore to make sure that only one thing can send a
-   heartbeat at one time, because we only have one copy of the data.
-   The semaphore is claimed when the set_timeout is sent and freed
-   when both messages are free. */
+/*
+ * We use a mutex to make sure that only one thing can send a
+ * heartbeat at one time, because we only have one copy of the data.
+ * The semaphore is claimed when the set_timeout is sent and freed
+ * when both messages are free.
+ */
 static atomic_t heartbeat_tofree = ATOMIC_INIT(0);
 static DEFINE_MUTEX(heartbeat_lock);
 static DECLARE_COMPLETION(heartbeat_wait);
@@ -557,15 +569,13 @@ static void heartbeat_free_recv(struct ipmi_recv_msg *msg)
     if (atomic_dec_and_test(&heartbeat_tofree))
            complete(&heartbeat_wait);
 }
-static struct ipmi_smi_msg heartbeat_smi_msg =
-{
+static struct ipmi_smi_msg heartbeat_smi_msg = {
        .done = heartbeat_free_smi
 };
-static struct ipmi_recv_msg heartbeat_recv_msg =
-{
+static struct ipmi_recv_msg heartbeat_recv_msg = {
        .done = heartbeat_free_recv
 };
+
 static int ipmi_heartbeat(void)
 {
        struct kernel_ipmi_msg            msg;
@@ -580,10 +590,12 @@ static int ipmi_heartbeat(void)
                ipmi_watchdog_state = action_val;
                return ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
        } else if (pretimeout_since_last_heartbeat) {
-               /* A pretimeout occurred, make sure we set the timeout.
-                  We don't want to set the action, though, we want to
-                  leave that alone (thus it can't be combined with the
-                  above operation. */
+               /*
+                * A pretimeout occurred, make sure we set the timeout.
+                * We don't want to set the action, though, we want to
+                * leave that alone (thus it can't be combined with the
+                * above operation.
+                */
                return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
        }
 
@@ -591,8 +603,10 @@ static int ipmi_heartbeat(void)
 
        atomic_set(&heartbeat_tofree, 2);
 
-       /* Don't reset the timer if we have the timer turned off, that
-           re-enables the watchdog. */
+       /*
+        * Don't reset the timer if we have the timer turned off, that
+        * re-enables the watchdog.
+        */
        if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) {
                mutex_unlock(&heartbeat_lock);
                return 0;
@@ -625,10 +639,12 @@ static int ipmi_heartbeat(void)
        wait_for_completion(&heartbeat_wait);
 
        if (heartbeat_recv_msg.msg.data[0] != 0) {
-           /* Got an error in the heartbeat response.  It was already
-              reported in ipmi_wdog_msg_handler, but we should return
-              an error here. */
-           rv = -EINVAL;
+               /*
+                * Got an error in the heartbeat response.  It was already
+                * reported in ipmi_wdog_msg_handler, but we should return
+                * an error here.
+                */
+               rv = -EINVAL;
        }
 
        mutex_unlock(&heartbeat_lock);
@@ -636,8 +652,7 @@ static int ipmi_heartbeat(void)
        return rv;
 }
 
-static struct watchdog_info ident =
-{
+static struct watchdog_info ident = {
        .options        = 0,    /* WDIOF_SETTIMEOUT, */
        .firmware_version = 1,
        .identity       = "IPMI"
@@ -650,7 +665,7 @@ static int ipmi_ioctl(struct inode *inode, struct file *file,
        int i;
        int val;
 
-       switch(cmd) {
+       switch (cmd) {
        case WDIOC_GETSUPPORT:
                i = copy_to_user(argp, &ident, sizeof(ident));
                return i ? -EFAULT : 0;
@@ -690,15 +705,13 @@ static int ipmi_ioctl(struct inode *inode, struct file *file,
                i = copy_from_user(&val, argp, sizeof(int));
                if (i)
                        return -EFAULT;
-               if (val & WDIOS_DISABLECARD)
-               {
+               if (val & WDIOS_DISABLECARD) {
                        ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
                        ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
                        ipmi_start_timer_on_heartbeat = 0;
                }
 
-               if (val & WDIOS_ENABLECARD)
-               {
+               if (val & WDIOS_ENABLECARD) {
                        ipmi_watchdog_state = action_val;
                        ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
                }
@@ -724,13 +737,13 @@ static ssize_t ipmi_write(struct file *file,
        int rv;
 
        if (len) {
-               if (!nowayout) {
-                       size_t i;
+               if (!nowayout) {
+                       size_t i;
 
                        /* In case it was set long ago */
                        expect_close = 0;
 
-                       for (i = 0; i != len; i++) {
+                       for (i = 0; i != len; i++) {
                                char c;
 
                                if (get_user(c, buf + i))
@@ -758,15 +771,17 @@ static ssize_t ipmi_read(struct file *file,
        if (count <= 0)
                return 0;
 
-       /* Reading returns if the pretimeout has gone off, and it only does
-          it once per pretimeout. */
+       /*
+        * Reading returns if the pretimeout has gone off, and it only does
+        * it once per pretimeout.
+        */
        spin_lock(&ipmi_read_lock);
        if (!data_to_read) {
                if (file->f_flags & O_NONBLOCK) {
                        rv = -EAGAIN;
                        goto out;
                }
-               
+
                init_waitqueue_entry(&wait, current);
                add_wait_queue(&read_q, &wait);
                while (!data_to_read) {
@@ -776,7 +791,7 @@ static ssize_t ipmi_read(struct file *file,
                        spin_lock(&ipmi_read_lock);
                }
                remove_wait_queue(&read_q, &wait);
-           
+
                if (signal_pending(current)) {
                        rv = -ERESTARTSYS;
                        goto out;
@@ -799,25 +814,27 @@ static ssize_t ipmi_read(struct file *file,
 
 static int ipmi_open(struct inode *ino, struct file *filep)
 {
-        switch (iminor(ino)) {
-        case WATCHDOG_MINOR:
+       switch (iminor(ino)) {
+       case WATCHDOG_MINOR:
                if (test_and_set_bit(0, &ipmi_wdog_open))
-                        return -EBUSY;
+                       return -EBUSY;
 
-               /* Don't start the timer now, let it start on the
-                  first heartbeat. */
+               /*
+                * Don't start the timer now, let it start on the
+                * first heartbeat.
+                */
                ipmi_start_timer_on_heartbeat = 1;
                return nonseekable_open(ino, filep);
 
        default:
                return (-ENODEV);
-        }
+       }
 }
 
 static unsigned int ipmi_poll(struct file *file, poll_table *wait)
 {
        unsigned int mask = 0;
-       
+
        poll_wait(file, &read_q, wait);
 
        spin_lock(&ipmi_read_lock);
@@ -851,7 +868,7 @@ static int ipmi_close(struct inode *ino, struct file *filep)
                clear_bit(0, &ipmi_wdog_open);
        }
 
-       ipmi_fasync (-1, filep, 0);
+       ipmi_fasync(-1, filep, 0);
        expect_close = 0;
 
        return 0;
@@ -882,7 +899,7 @@ static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg,
                       msg->msg.data[0],
                       msg->msg.cmd);
        }
-       
+
        ipmi_free_recv_msg(msg);
 }
 
@@ -902,14 +919,14 @@ static void ipmi_wdog_pretimeout_handler(void *handler_data)
                }
        }
 
-       /* On some machines, the heartbeat will give
-          an error and not work unless we re-enable
-          the timer.   So do so. */
+       /*
+        * On some machines, the heartbeat will give an error and not
+        * work unless we re-enable the timer.  So do so.
+        */
        pretimeout_since_last_heartbeat = 1;
 }
 
-static struct ipmi_user_hndl ipmi_hndlrs =
-{
+static struct ipmi_user_hndl ipmi_hndlrs = {
        .ipmi_recv_hndl           = ipmi_wdog_msg_handler,
        .ipmi_watchdog_pretimeout = ipmi_wdog_pretimeout_handler
 };
@@ -949,8 +966,10 @@ static void ipmi_register_watchdog(int ipmi_intf)
                int old_timeout = timeout;
                int old_preop_val = preop_val;
 
-               /* Set the pretimeout to go off in a second and give
-                  ourselves plenty of time to stop the timer. */
+               /*
+                * Set the pretimeout to go off in a second and give
+                * ourselves plenty of time to stop the timer.
+                */
                ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
                preop_val = WDOG_PREOP_NONE; /* Make sure nothing happens */
                pretimeout = 99;
@@ -974,7 +993,7 @@ static void ipmi_register_watchdog(int ipmi_intf)
                               " occur.  The NMI pretimeout will"
                               " likely not work\n");
                }
      out_restore:
+ out_restore:
                testing_nmi = 0;
                preop_val = old_preop_val;
                pretimeout = old_pretimeout;
@@ -1009,9 +1028,11 @@ static void ipmi_unregister_watchdog(int ipmi_intf)
        /* Make sure no one can call us any more. */
        misc_deregister(&ipmi_wdog_miscdev);
 
-       /* Wait to make sure the message makes it out.  The lower layer has
-          pointers to our buffers, we want to make sure they are done before
-          we release our memory. */
+       /*
+        * Wait to make sure the message makes it out.  The lower layer has
+        * pointers to our buffers, we want to make sure they are done before
+        * we release our memory.
+        */
        while (atomic_read(&set_timeout_tofree))
                schedule_timeout_uninterruptible(1);
 
@@ -1052,15 +1073,17 @@ ipmi_nmi(struct notifier_block *self, unsigned long val, void *data)
                return NOTIFY_STOP;
        }
 
-        /* If we are not expecting a timeout, ignore it. */
+       /* If we are not expecting a timeout, ignore it. */
        if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE)
                return NOTIFY_OK;
 
        if (preaction_val != WDOG_PRETIMEOUT_NMI)
                return NOTIFY_OK;
 
-       /* If no one else handled the NMI, we assume it was the IPMI
-           watchdog. */
+       /*
+        * If no one else handled the NMI, we assume it was the IPMI
+        * watchdog.
+        */
        if (preop_val == WDOG_PREOP_PANIC) {
                /* On some machines, the heartbeat will give
                   an error and not work unless we re-enable
@@ -1082,7 +1105,7 @@ static int wdog_reboot_handler(struct notifier_block *this,
                               unsigned long         code,
                               void                  *unused)
 {
-       static int reboot_event_handled = 0;
+       static int reboot_event_handled;
 
        if ((watchdog_user) && (!reboot_event_handled)) {
                /* Make sure we only do this once. */
@@ -1115,7 +1138,7 @@ static int wdog_panic_handler(struct notifier_block *this,
                              unsigned long         event,
                              void                  *unused)
 {
-       static int panic_event_handled = 0;
+       static int panic_event_handled;
 
        /* On a panic, if we have a panic timeout, make sure to extend
           the watchdog timer to a reasonable value to complete the
@@ -1125,7 +1148,7 @@ static int wdog_panic_handler(struct notifier_block *this,
            ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
                /* Make sure we do this only once. */
                panic_event_handled = 1;
-           
+
                timeout = 255;
                pretimeout = 0;
                panic_halt_ipmi_set_timeout();
@@ -1151,8 +1174,7 @@ static void ipmi_smi_gone(int if_num)
        ipmi_unregister_watchdog(if_num);
 }
 
-static struct ipmi_smi_watcher smi_watcher =
-{
+static struct ipmi_smi_watcher smi_watcher = {
        .owner    = THIS_MODULE,
        .new_smi  = ipmi_new_smi,
        .smi_gone = ipmi_smi_gone
index eba2883b630ede817677c54a7cfe3e94f1582be1..4f3cefa8eb0e28cd0632983e66cebc63e5bb82ae 100644 (file)
 #include <linux/delay.h>
 #include <linux/ioport.h>
 
-#include <asm/uaccess.h>
-#include <asm/io.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
 #include <asm/system.h>
 
 #include <linux/pci.h>
@@ -189,7 +189,7 @@ struct      isi_board {
        unsigned short          status;
        unsigned short          port_status; /* each bit for each port */
        unsigned short          shift_count;
-       struct isi_port         * ports;
+       struct isi_port         *ports;
        signed char             count;
        spinlock_t              card_lock; /* Card wide lock 11/5/00 -sameer */
        unsigned long           flags;
@@ -205,11 +205,11 @@ struct    isi_port {
        u16                     channel;
        u16                     status;
        u16                     closing_wait;
-       struct isi_board        * card;
-       struct tty_struct       * tty;
+       struct isi_board        *card;
+       struct tty_struct       *tty;
        wait_queue_head_t       close_wait;
        wait_queue_head_t       open_wait;
-       unsigned char           * xmit_buf;
+       unsigned char           *xmit_buf;
        int                     xmit_head;
        int                     xmit_tail;
        int                     xmit_cnt;
@@ -405,7 +405,7 @@ static void isicom_tx(unsigned long _data)
 
        /*      find next active board  */
        card = (prev_card + 1) & 0x0003;
-       while(count-- > 0) {
+       while (count-- > 0) {
                if (isi_card[card].status & BOARD_ACTIVE)
                        break;
                card = (card + 1) & 0x0003;
@@ -428,7 +428,7 @@ static void isicom_tx(unsigned long _data)
        if (retries >= 100)
                goto unlock;
 
-       for (;count > 0;count--, port++) {
+       for (; count > 0; count--, port++) {
                /* port not active or tx disabled to force flow control */
                if (!(port->flags & ASYNC_INITIALIZED) ||
                                !(port->status & ISI_TXOK))
@@ -471,9 +471,10 @@ static void isicom_tx(unsigned long _data)
                                        break;
                                }
                        }
-                       if (cnt <= 0) break;
+                       if (cnt <= 0)
+                               break;
                        word_count = cnt >> 1;
-                       outsw(base, port->xmit_buf+port->xmit_tail,word_count);
+                       outsw(base, port->xmit_buf+port->xmit_tail, word_count);
                        port->xmit_tail = (port->xmit_tail
                                + (word_count << 1)) & (SERIAL_XMIT_SIZE - 1);
                        txcount -= (word_count << 1);
@@ -556,7 +557,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
        tty = port->tty;
        if (tty == NULL) {
                word_count = byte_count >> 1;
-               while(byte_count > 1) {
+               while (byte_count > 1) {
                        inw(base);
                        byte_count -= 2;
                }
@@ -569,7 +570,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
 
        if (header & 0x8000) {          /* Status Packet */
                header = inw(base);
-               switch(header & 0xff) {
+               switch (header & 0xff) {
                case 0: /* Change in EIA signals */
                        if (port->flags & ASYNC_CHECK_CD) {
                                if (port->status & ISI_DCD) {
@@ -656,7 +657,8 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
                if (byte_count > 0) {
                        pr_dbg("Intr(0x%lx:%d): Flip buffer overflow! dropping "
                                "bytes...\n", base, channel + 1);
-                       while(byte_count > 0) { /* drain out unread xtra data */
+               /* drain out unread xtra data */
+               while (byte_count > 0) {
                                inw(base);
                                byte_count -= 2;
                        }
@@ -679,8 +681,11 @@ static void isicom_config_port(struct isi_port *port)
                shift_count = card->shift_count;
        unsigned char flow_ctrl;
 
-       if (!(tty = port->tty) || !tty->termios)
+       tty = port->tty;
+
+       if (tty == NULL)
                return;
+       /* FIXME: Switch to new tty baud API */
        baud = C_BAUD(tty);
        if (baud & CBAUDEX) {
                baud &= ~CBAUDEX;
@@ -706,7 +711,7 @@ static void isicom_config_port(struct isi_port *port)
                if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
                        baud++; /*  57.6 Kbps */
                if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-                       baud +=2; /*  115  Kbps */
+                       baud += 2; /*  115  Kbps */
                if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
                        baud += 3; /* 230 kbps*/
                if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
@@ -716,15 +721,14 @@ static void isicom_config_port(struct isi_port *port)
                /* hang up */
                drop_dtr(port);
                return;
-       }
-       else
+       } else
                raise_dtr(port);
 
        if (WaitTillCardIsFree(base) == 0) {
-               outw(0x8000 | (channel << shift_count) |0x03, base);
+               outw(0x8000 | (channel << shift_count) | 0x03, base);
                outw(linuxb_to_isib[baud] << 8 | 0x03, base);
                channel_setup = 0;
-               switch(C_CSIZE(tty)) {
+               switch (C_CSIZE(tty)) {
                case CS5:
                        channel_setup |= ISICOM_CS5;
                        break;
@@ -767,7 +771,7 @@ static void isicom_config_port(struct isi_port *port)
                flow_ctrl |= ISICOM_INITIATE_XONXOFF;
 
        if (WaitTillCardIsFree(base) == 0) {
-               outw(0x8000 | (channel << shift_count) |0x04, base);
+               outw(0x8000 | (channel << shift_count) | 0x04, base);
                outw(flow_ctrl << 8 | 0x05, base);
                outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base);
                InterruptTheCard(base);
@@ -805,20 +809,17 @@ static int isicom_setup_port(struct isi_port *port)
        struct isi_board *card = port->card;
        unsigned long flags;
 
-       if (port->flags & ASYNC_INITIALIZED) {
+       if (port->flags & ASYNC_INITIALIZED)
                return 0;
-       }
        if (!port->xmit_buf) {
-               unsigned long page;
-
-               if (!(page = get_zeroed_page(GFP_KERNEL)))
+               /* Relies on BKL */
+               unsigned long page  = get_zeroed_page(GFP_KERNEL);
+               if (page == 0)
                        return -ENOMEM;
-
-               if (port->xmit_buf) {
+               if (port->xmit_buf)
                        free_page(page);
-                       return -ERESTARTSYS;
-               }
-               port->xmit_buf = (unsigned char *) page;
+               else
+                       port->xmit_buf = (unsigned char *) page;
        }
 
        spin_lock_irqsave(&card->card_lock, flags);
@@ -949,21 +950,18 @@ static int isicom_open(struct tty_struct *tty, struct file *filp)
        port->count++;
        tty->driver_data = port;
        port->tty = tty;
-       if ((error = isicom_setup_port(port))!=0)
-               return error;
-       if ((error = block_til_ready(tty, filp, port))!=0)
-               return error;
-
-       return 0;
+       error = isicom_setup_port(port);
+       if (error == 0)
+               error = block_til_ready(tty, filp, port);
+       return error;
 }
 
 /* close et all */
 
 static inline void isicom_shutdown_board(struct isi_board *bp)
 {
-       if (bp->status & BOARD_ACTIVE) {
+       if (bp->status & BOARD_ACTIVE)
                bp->status &= ~BOARD_ACTIVE;
-       }
 }
 
 /* card->lock HAS to be held */
@@ -1012,6 +1010,22 @@ static void isicom_shutdown_port(struct isi_port *port)
        }
 }
 
+static void isicom_flush_buffer(struct tty_struct *tty)
+{
+       struct isi_port *port = tty->driver_data;
+       struct isi_board *card = port->card;
+       unsigned long flags;
+
+       if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer"))
+               return;
+
+       spin_lock_irqsave(&card->card_lock, flags);
+       port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+       spin_unlock_irqrestore(&card->card_lock, flags);
+
+       tty_wakeup(tty);
+}
+
 static void isicom_close(struct tty_struct *tty, struct file *filp)
 {
        struct isi_port *port = tty->driver_data;
@@ -1065,8 +1079,7 @@ static void isicom_close(struct tty_struct *tty, struct file *filp)
        isicom_shutdown_port(port);
        spin_unlock_irqrestore(&card->card_lock, flags);
 
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       isicom_flush_buffer(tty);
        tty_ldisc_flush(tty);
 
        spin_lock_irqsave(&card->card_lock, flags);
@@ -1104,7 +1117,7 @@ static int isicom_write(struct tty_struct *tty,   const unsigned char *buf,
 
        spin_lock_irqsave(&card->card_lock, flags);
 
-       while(1) {
+       while (1) {
                cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt
                                - 1, SERIAL_XMIT_SIZE - port->xmit_head));
                if (cnt <= 0)
@@ -1125,28 +1138,29 @@ static int isicom_write(struct tty_struct *tty, const unsigned char *buf,
 }
 
 /* put_char et all */
-static void isicom_put_char(struct tty_struct *tty, unsigned char ch)
+static int isicom_put_char(struct tty_struct *tty, unsigned char ch)
 {
        struct isi_port *port = tty->driver_data;
        struct isi_board *card = port->card;
        unsigned long flags;
 
        if (isicom_paranoia_check(port, tty->name, "isicom_put_char"))
-               return;
+               return 0;
 
        if (!port->xmit_buf)
-               return;
+               return 0;
 
        spin_lock_irqsave(&card->card_lock, flags);
        if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
                spin_unlock_irqrestore(&card->card_lock, flags);
-               return;
+               return 0;
        }
 
        port->xmit_buf[port->xmit_head++] = ch;
        port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
        port->xmit_cnt++;
        spin_unlock_irqrestore(&card->card_lock, flags);
+       return 1;
 }
 
 /* flush_chars et all */
@@ -1258,6 +1272,8 @@ static int isicom_set_serial_info(struct isi_port *port,
        if (copy_from_user(&newinfo, info, sizeof(newinfo)))
                return -EFAULT;
 
+       lock_kernel();
+
        reconfig_port = ((port->flags & ASYNC_SPD_MASK) !=
                (newinfo.flags & ASYNC_SPD_MASK));
 
@@ -1265,12 +1281,13 @@ static int isicom_set_serial_info(struct isi_port *port,
                if ((newinfo.close_delay != port->close_delay) ||
                                (newinfo.closing_wait != port->closing_wait) ||
                                ((newinfo.flags & ~ASYNC_USR_MASK) !=
-                               (port->flags & ~ASYNC_USR_MASK)))
+                               (port->flags & ~ASYNC_USR_MASK))) {
+                       unlock_kernel();
                        return -EPERM;
-               port->flags = ((port->flags & ~ ASYNC_USR_MASK) |
+               }
+               port->flags = ((port->flags & ~ASYNC_USR_MASK) |
                                (newinfo.flags & ASYNC_USR_MASK));
-       }
-       else {
+       } else {
                port->close_delay = newinfo.close_delay;
                port->closing_wait = newinfo.closing_wait;
                port->flags = ((port->flags & ~ASYNC_FLAGS) |
@@ -1282,6 +1299,7 @@ static int isicom_set_serial_info(struct isi_port *port,
                isicom_config_port(port);
                spin_unlock_irqrestore(&port->card->card_lock, flags);
        }
+       unlock_kernel();
        return 0;
 }
 
@@ -1290,6 +1308,7 @@ static int isicom_get_serial_info(struct isi_port *port,
 {
        struct serial_struct out_info;
 
+       lock_kernel();
        memset(&out_info, 0, sizeof(out_info));
 /*     out_info.type = ? */
        out_info.line = port - isi_ports;
@@ -1299,6 +1318,7 @@ static int isicom_get_serial_info(struct isi_port *port,
 /*     out_info.baud_base = ? */
        out_info.close_delay = port->close_delay;
        out_info.closing_wait = port->closing_wait;
+       unlock_kernel();
        if (copy_to_user(info, &out_info, sizeof(out_info)))
                return -EFAULT;
        return 0;
@@ -1314,7 +1334,7 @@ static int isicom_ioctl(struct tty_struct *tty, struct file *filp,
        if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
                return -ENODEV;
 
-       switch(cmd) {
+       switch (cmd) {
        case TCSBRK:
                retval = tty_check_change(tty);
                if (retval)
@@ -1331,19 +1351,6 @@ static int isicom_ioctl(struct tty_struct *tty, struct file *filp,
                tty_wait_until_sent(tty, 0);
                isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4);
                return 0;
-
-       case TIOCGSOFTCAR:
-               return put_user(C_CLOCAL(tty) ? 1 : 0,
-                               (unsigned long __user *)argp);
-
-       case TIOCSSOFTCAR:
-               if (get_user(arg, (unsigned long __user *) argp))
-                       return -EFAULT;
-               tty->termios->c_cflag =
-                       ((tty->termios->c_cflag & ~CLOCAL) |
-                       (arg ? CLOCAL : 0));
-               return 0;
-
        case TIOCGSERIAL:
                return isicom_get_serial_info(port, argp);
 
@@ -1453,22 +1460,6 @@ static void isicom_hangup(struct tty_struct *tty)
        wake_up_interruptible(&port->open_wait);
 }
 
-/* flush_buffer et all */
-static void isicom_flush_buffer(struct tty_struct *tty)
-{
-       struct isi_port *port = tty->driver_data;
-       struct isi_board *card = port->card;
-       unsigned long flags;
-
-       if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer"))
-               return;
-
-       spin_lock_irqsave(&card->card_lock, flags);
-       port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-       spin_unlock_irqrestore(&card->card_lock, flags);
-
-       tty_wakeup(tty);
-}
 
 /*
  * Driver init and deinit functions
@@ -1592,7 +1583,7 @@ static int __devinit load_firmware(struct pci_dev *pdev,
        default:
                dev_err(&pdev->dev, "Unknown signature.\n");
                goto end;
-       }
+       }
 
        retval = request_firmware(&fw, name, &pdev->dev);
        if (retval)
@@ -1620,7 +1611,8 @@ static int __devinit load_firmware(struct pci_dev *pdev,
                if (WaitTillCardIsFree(base))
                        goto errrelfw;
 
-               if ((status = inw(base + 0x4)) != 0) {
+               status = inw(base + 0x4);
+               if (status != 0) {
                        dev_warn(&pdev->dev, "Card%d rejected load header:\n"
                                KERN_WARNING "Address:0x%x\n"
                                KERN_WARNING "Count:0x%x\n"
@@ -1637,12 +1629,13 @@ static int __devinit load_firmware(struct pci_dev *pdev,
                if (WaitTillCardIsFree(base))
                        goto errrelfw;
 
-               if ((status = inw(base + 0x4)) != 0) {
+               status = inw(base + 0x4);
+               if (status != 0) {
                        dev_err(&pdev->dev, "Card%d got out of sync.Card "
                                "Status:0x%x\n", index + 1, status);
                        goto errrelfw;
                }
-       }
+       }
 
 /* XXX: should we test it by reading it back and comparing with original like
  * in load firmware package? */
@@ -1666,7 +1659,8 @@ static int __devinit load_firmware(struct pci_dev *pdev,
                if (WaitTillCardIsFree(base))
                        goto errrelfw;
 
-               if ((status = inw(base + 0x4)) != 0) {
+               status = inw(base + 0x4);
+               if (status != 0) {
                        dev_warn(&pdev->dev, "Card%d rejected verify header:\n"
                                KERN_WARNING "Address:0x%x\n"
                                KERN_WARNING "Count:0x%x\n"
@@ -1699,7 +1693,8 @@ static int __devinit load_firmware(struct pci_dev *pdev,
                if (WaitTillCardIsFree(base))
                        goto errrelfw;
 
-               if ((status = inw(base + 0x4)) != 0) {
+               status = inw(base + 0x4);
+               if (status != 0) {
                        dev_err(&pdev->dev, "Card%d verify got out of sync. "
                                "Card Status:0x%x\n", index + 1, status);
                        goto errrelfw;
@@ -1764,7 +1759,7 @@ static int __devinit isicom_probe(struct pci_dev *pdev,
                        index + 1);
                retval = -EBUSY;
                goto errdec;
-       }
+       }
 
        retval = request_irq(board->irq, isicom_interrupt,
                        IRQF_SHARED | IRQF_DISABLED, ISICOM_NAME, board);
@@ -1818,7 +1813,7 @@ static int __init isicom_init(void)
        int retval, idx, channel;
        struct isi_port *port;
 
-       for(idx = 0; idx < BOARD_COUNT; idx++) {
+       for (idx = 0; idx < BOARD_COUNT; idx++) {
                port = &isi_ports[idx * 16];
                isi_card[idx].ports = port;
                spin_lock_init(&isi_card[idx].card_lock);
@@ -1832,7 +1827,7 @@ static int __init isicom_init(void)
                        init_waitqueue_head(&port->open_wait);
                        init_waitqueue_head(&port->close_wait);
                        /*  . . .  */
-               }
+               }
                isi_card[idx].base = 0;
                isi_card[idx].irq = 0;
        }
index c645455c3fd1552ed9f7932bd28dabb7f963280d..7c8b62f162bf115c0c74ab184f333625f65df0c4 100644 (file)
@@ -1682,16 +1682,6 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
        rc = 0;
 
        switch (cmd) {
-       case TIOCGSOFTCAR:
-               rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
-                       (unsigned __user *) arg);
-               break;
-       case TIOCSSOFTCAR:
-               if ((rc = get_user(ival, (unsigned __user *) arg)) == 0)
-                       tty->termios->c_cflag =
-                               (tty->termios->c_cflag & ~CLOCAL) |
-                               (ival ? CLOCAL : 0);
-               break;
        case TIOCGSERIAL:
                rc = stli_getserial(portp, argp);
                break;
@@ -3267,7 +3257,7 @@ static int stli_initecp(struct stlibrd *brdp)
  */
        EBRDINIT(brdp);
 
-       brdp->membase = ioremap(brdp->memaddr, brdp->memsize);
+       brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize);
        if (brdp->membase == NULL) {
                retval = -ENOMEM;
                goto err_reg;
@@ -3424,7 +3414,7 @@ static int stli_initonb(struct stlibrd *brdp)
  */
        EBRDINIT(brdp);
 
-       brdp->membase = ioremap(brdp->memaddr, brdp->memsize);
+       brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize);
        if (brdp->membase == NULL) {
                retval = -ENOMEM;
                goto err_reg;
@@ -3675,7 +3665,7 @@ static int stli_eisamemprobe(struct stlibrd *brdp)
  */
        for (i = 0; (i < stli_eisamempsize); i++) {
                brdp->memaddr = stli_eisamemprobeaddrs[i];
-               brdp->membase = ioremap(brdp->memaddr, brdp->memsize);
+               brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize);
                if (brdp->membase == NULL)
                        continue;
 
@@ -4433,6 +4423,8 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
        done = 0;
        rc = 0;
 
+       lock_kernel();
+
        switch (cmd) {
        case COM_GETPORTSTATS:
                rc = stli_getportstats(NULL, argp);
@@ -4455,6 +4447,7 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
                done++;
                break;
        }
+       unlock_kernel();
 
        if (done)
                return rc;
@@ -4472,6 +4465,8 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
        if (brdp->state == 0)
                return -ENODEV;
 
+       lock_kernel();
+
        switch (cmd) {
        case STL_BINTR:
                EBRDINTR(brdp);
@@ -4494,6 +4489,7 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
                rc = -ENOIOCTLCMD;
                break;
        }
+       unlock_kernel();
        return rc;
 }
 
index 60b934adea65139c5c802b995e6be28950cc6e2e..7f7e798c13844f0a8c8e2630057566c9ed5a66cf 100644 (file)
@@ -110,6 +110,7 @@ const int max_vals[] = {
 const int NR_TYPES = ARRAY_SIZE(max_vals);
 
 struct kbd_struct kbd_table[MAX_NR_CONSOLES];
+EXPORT_SYMBOL_GPL(kbd_table);
 static struct kbd_struct *kbd = kbd_table;
 
 struct vt_spawn_console vt_spawn_con = {
@@ -260,6 +261,7 @@ void kd_mksound(unsigned int hz, unsigned int ticks)
        } else
                kd_nosound(0);
 }
+EXPORT_SYMBOL(kd_mksound);
 
 /*
  * Setting the keyboard rate.
@@ -1230,7 +1232,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
 
        if (rep &&
            (!vc_kbd_mode(kbd, VC_REPEAT) ||
-            (tty && !L_ECHO(tty) && tty->driver->chars_in_buffer(tty)))) {
+            (tty && !L_ECHO(tty) && tty_chars_in_buffer(tty)))) {
                /*
                 * Don't repeat a key if the input buffers are not empty and the
                 * characters get aren't echoed locally. This makes key repeat
index e83623ead4414efaf02a8d7e124f5719b18479c4..934ffafedaea207131f7d193bed9e75c929f4db9 100644 (file)
@@ -364,6 +364,7 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
        return 0;
 }
 
+#ifdef CONFIG_DEVKMEM
 static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
 {
        unsigned long pfn;
@@ -384,6 +385,7 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
        vma->vm_pgoff = pfn;
        return mmap_mem(file, vma);
 }
+#endif
 
 #ifdef CONFIG_CRASH_DUMP
 /*
@@ -422,6 +424,7 @@ static ssize_t read_oldmem(struct file *file, char __user *buf,
 extern long vread(char *buf, char *addr, unsigned long count);
 extern long vwrite(char *buf, char *addr, unsigned long count);
 
+#ifdef CONFIG_DEVKMEM
 /*
  * This function reads the *virtual* memory as seen by the kernel.
  */
@@ -626,6 +629,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
        *ppos = p;
        return virtr + wrote;
 }
+#endif
 
 #ifdef CONFIG_DEVPORT
 static ssize_t read_port(struct file * file, char __user * buf,
@@ -803,6 +807,7 @@ static const struct file_operations mem_fops = {
        .get_unmapped_area = get_unmapped_area_mem,
 };
 
+#ifdef CONFIG_DEVKMEM
 static const struct file_operations kmem_fops = {
        .llseek         = memory_lseek,
        .read           = read_kmem,
@@ -811,6 +816,7 @@ static const struct file_operations kmem_fops = {
        .open           = open_kmem,
        .get_unmapped_area = get_unmapped_area_mem,
 };
+#endif
 
 static const struct file_operations null_fops = {
        .llseek         = null_lseek,
@@ -889,11 +895,13 @@ static int memory_open(struct inode * inode, struct file * filp)
                        filp->f_mapping->backing_dev_info =
                                &directly_mappable_cdev_bdi;
                        break;
+#ifdef CONFIG_DEVKMEM
                case 2:
                        filp->f_op = &kmem_fops;
                        filp->f_mapping->backing_dev_info =
                                &directly_mappable_cdev_bdi;
                        break;
+#endif
                case 3:
                        filp->f_op = &null_fops;
                        break;
@@ -942,7 +950,9 @@ static const struct {
        const struct file_operations    *fops;
 } devlist[] = { /* list of minor devices */
        {1, "mem",     S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
+#ifdef CONFIG_DEVKMEM
        {2, "kmem",    S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
+#endif
        {3, "null",    S_IRUGO | S_IWUGO,           &null_fops},
 #ifdef CONFIG_DEVPORT
        {4, "port",    S_IRUSR | S_IWUSR | S_IRGRP, &port_fops},
index 4d058dadbfcc8c6324b7c4e224530289145140b3..eaace0db0ff4b65d61418e17db6b401c37fc3507 100644 (file)
@@ -263,23 +263,26 @@ EXPORT_SYMBOL(misc_deregister);
 
 static int __init misc_init(void)
 {
-#ifdef CONFIG_PROC_FS
-       struct proc_dir_entry *ent;
+       int err;
 
-       ent = create_proc_entry("misc", 0, NULL);
-       if (ent)
-               ent->proc_fops = &misc_proc_fops;
+#ifdef CONFIG_PROC_FS
+       proc_create("misc", 0, NULL, &misc_proc_fops);
 #endif
        misc_class = class_create(THIS_MODULE, "misc");
+       err = PTR_ERR(misc_class);
        if (IS_ERR(misc_class))
-               return PTR_ERR(misc_class);
+               goto fail_remove;
 
-       if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
-               printk("unable to get major %d for misc devices\n",
-                      MISC_MAJOR);
-               class_destroy(misc_class);
-               return -EIO;
-       }
+       err = -EIO;
+       if (register_chrdev(MISC_MAJOR,"misc",&misc_fops))
+               goto fail_printk;
        return 0;
+
+fail_printk:
+       printk("unable to get major %d for misc devices\n", MISC_MAJOR);
+       class_destroy(misc_class);
+fail_remove:
+       remove_proc_entry("misc", NULL);
+       return err;
 }
 subsys_initcall(misc_init);
index e60a74c66e3dfa05c00eb45596829e77932ce5c1..d83db5d880e068ac4296c2b07767d849067a1037 100644 (file)
@@ -74,9 +74,8 @@ static const struct file_operations mmtimer_fops = {
  * We only have comparison registers RTC1-4 currently available per
  * node.  RTC0 is used by SAL.
  */
-#define NUM_COMPARATORS 3
 /* Check for an RTC interrupt pending */
-static int inline mmtimer_int_pending(int comparator)
+static int mmtimer_int_pending(int comparator)
 {
        if (HUB_L((unsigned long *)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED)) &
                        SH_EVENT_OCCURRED_RTC1_INT_MASK << comparator)
@@ -84,15 +83,16 @@ static int inline mmtimer_int_pending(int comparator)
        else
                return 0;
 }
+
 /* Clear the RTC interrupt pending bit */
-static void inline mmtimer_clr_int_pending(int comparator)
+static void mmtimer_clr_int_pending(int comparator)
 {
        HUB_S((u64 *)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS),
                SH_EVENT_OCCURRED_RTC1_INT_MASK << comparator);
 }
 
 /* Setup timer on comparator RTC1 */
-static void inline mmtimer_setup_int_0(u64 expires)
+static void mmtimer_setup_int_0(int cpu, u64 expires)
 {
        u64 val;
 
@@ -106,7 +106,7 @@ static void inline mmtimer_setup_int_0(u64 expires)
        mmtimer_clr_int_pending(0);
 
        val = ((u64)SGI_MMTIMER_VECTOR << SH_RTC1_INT_CONFIG_IDX_SHFT) |
-               ((u64)cpu_physical_id(smp_processor_id()) <<
+               ((u64)cpu_physical_id(cpu) <<
                        SH_RTC1_INT_CONFIG_PID_SHFT);
 
        /* Set configuration */
@@ -122,7 +122,7 @@ static void inline mmtimer_setup_int_0(u64 expires)
 }
 
 /* Setup timer on comparator RTC2 */
-static void inline mmtimer_setup_int_1(u64 expires)
+static void mmtimer_setup_int_1(int cpu, u64 expires)
 {
        u64 val;
 
@@ -133,7 +133,7 @@ static void inline mmtimer_setup_int_1(u64 expires)
        mmtimer_clr_int_pending(1);
 
        val = ((u64)SGI_MMTIMER_VECTOR << SH_RTC2_INT_CONFIG_IDX_SHFT) |
-               ((u64)cpu_physical_id(smp_processor_id()) <<
+               ((u64)cpu_physical_id(cpu) <<
                        SH_RTC2_INT_CONFIG_PID_SHFT);
 
        HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC2_INT_CONFIG), val);
@@ -144,7 +144,7 @@ static void inline mmtimer_setup_int_1(u64 expires)
 }
 
 /* Setup timer on comparator RTC3 */
-static void inline mmtimer_setup_int_2(u64 expires)
+static void mmtimer_setup_int_2(int cpu, u64 expires)
 {
        u64 val;
 
@@ -155,7 +155,7 @@ static void inline mmtimer_setup_int_2(u64 expires)
        mmtimer_clr_int_pending(2);
 
        val = ((u64)SGI_MMTIMER_VECTOR << SH_RTC3_INT_CONFIG_IDX_SHFT) |
-               ((u64)cpu_physical_id(smp_processor_id()) <<
+               ((u64)cpu_physical_id(cpu) <<
                        SH_RTC3_INT_CONFIG_PID_SHFT);
 
        HUB_S((u64 *)LOCAL_MMR_ADDR(SH_RTC3_INT_CONFIG), val);
@@ -170,22 +170,22 @@ static void inline mmtimer_setup_int_2(u64 expires)
  * in order to insure that the setup succeeds in a deterministic time frame.
  * It will check if the interrupt setup succeeded.
  */
-static int inline mmtimer_setup(int comparator, unsigned long expires)
+static int mmtimer_setup(int cpu, int comparator, unsigned long expires)
 {
 
        switch (comparator) {
        case 0:
-               mmtimer_setup_int_0(expires);
+               mmtimer_setup_int_0(cpu, expires);
                break;
        case 1:
-               mmtimer_setup_int_1(expires);
+               mmtimer_setup_int_1(cpu, expires);
                break;
        case 2:
-               mmtimer_setup_int_2(expires);
+               mmtimer_setup_int_2(cpu, expires);
                break;
        }
        /* We might've missed our expiration time */
-       if (rtc_time() < expires)
+       if (rtc_time() <= expires)
                return 1;
 
        /*
@@ -195,7 +195,7 @@ static int inline mmtimer_setup(int comparator, unsigned long expires)
        return mmtimer_int_pending(comparator);
 }
 
-static int inline mmtimer_disable_int(long nasid, int comparator)
+static int mmtimer_disable_int(long nasid, int comparator)
 {
        switch (comparator) {
        case 0:
@@ -216,18 +216,124 @@ static int inline mmtimer_disable_int(long nasid, int comparator)
        return 0;
 }
 
-#define TIMER_OFF 0xbadcabLL
+#define COMPARATOR     1               /* The comparator to use */
 
-/* There is one of these for each comparator */
-typedef struct mmtimer {
-       spinlock_t lock ____cacheline_aligned;
+#define TIMER_OFF      0xbadcabLL      /* Timer is not setup */
+#define TIMER_SET      0               /* Comparator is set for this timer */
+
+/* There is one of these for each timer */
+struct mmtimer {
+       struct rb_node list;
        struct k_itimer *timer;
-       int i;
        int cpu;
+};
+
+struct mmtimer_node {
+       spinlock_t lock ____cacheline_aligned;
+       struct rb_root timer_head;
+       struct rb_node *next;
        struct tasklet_struct tasklet;
-} mmtimer_t;
+};
+static struct mmtimer_node *timers;
+
+
+/*
+ * Add a new mmtimer struct to the node's mmtimer list.
+ * This function assumes the struct mmtimer_node is locked.
+ */
+static void mmtimer_add_list(struct mmtimer *n)
+{
+       int nodeid = n->timer->it.mmtimer.node;
+       unsigned long expires = n->timer->it.mmtimer.expires;
+       struct rb_node **link = &timers[nodeid].timer_head.rb_node;
+       struct rb_node *parent = NULL;
+       struct mmtimer *x;
+
+       /*
+        * Find the right place in the rbtree:
+        */
+       while (*link) {
+               parent = *link;
+               x = rb_entry(parent, struct mmtimer, list);
+
+               if (expires < x->timer->it.mmtimer.expires)
+                       link = &(*link)->rb_left;
+               else
+                       link = &(*link)->rb_right;
+       }
+
+       /*
+        * Insert the timer to the rbtree and check whether it
+        * replaces the first pending timer
+        */
+       rb_link_node(&n->list, parent, link);
+       rb_insert_color(&n->list, &timers[nodeid].timer_head);
+
+       if (!timers[nodeid].next || expires < rb_entry(timers[nodeid].next,
+                       struct mmtimer, list)->timer->it.mmtimer.expires)
+               timers[nodeid].next = &n->list;
+}
+
+/*
+ * Set the comparator for the next timer.
+ * This function assumes the struct mmtimer_node is locked.
+ */
+static void mmtimer_set_next_timer(int nodeid)
+{
+       struct mmtimer_node *n = &timers[nodeid];
+       struct mmtimer *x;
+       struct k_itimer *t;
+       int o;
+
+restart:
+       if (n->next == NULL)
+               return;
 
-static mmtimer_t ** timers;
+       x = rb_entry(n->next, struct mmtimer, list);
+       t = x->timer;
+       if (!t->it.mmtimer.incr) {
+               /* Not an interval timer */
+               if (!mmtimer_setup(x->cpu, COMPARATOR,
+                                       t->it.mmtimer.expires)) {
+                       /* Late setup, fire now */
+                       tasklet_schedule(&n->tasklet);
+               }
+               return;
+       }
+
+       /* Interval timer */
+       o = 0;
+       while (!mmtimer_setup(x->cpu, COMPARATOR, t->it.mmtimer.expires)) {
+               unsigned long e, e1;
+               struct rb_node *next;
+               t->it.mmtimer.expires += t->it.mmtimer.incr << o;
+               t->it_overrun += 1 << o;
+               o++;
+               if (o > 20) {
+                       printk(KERN_ALERT "mmtimer: cannot reschedule timer\n");
+                       t->it.mmtimer.clock = TIMER_OFF;
+                       n->next = rb_next(&x->list);
+                       rb_erase(&x->list, &n->timer_head);
+                       kfree(x);
+                       goto restart;
+               }
+
+               e = t->it.mmtimer.expires;
+               next = rb_next(&x->list);
+
+               if (next == NULL)
+                       continue;
+
+               e1 = rb_entry(next, struct mmtimer, list)->
+                       timer->it.mmtimer.expires;
+               if (e > e1) {
+                       n->next = next;
+                       rb_erase(&x->list, &n->timer_head);
+                       mmtimer_add_list(x);
+                       goto restart;
+               }
+       }
+}
 
 /**
  * mmtimer_ioctl - ioctl interface for /dev/mmtimer
@@ -390,35 +496,6 @@ static int sgi_clock_set(clockid_t clockid, struct timespec *tp)
        return 0;
 }
 
-/*
- * Schedule the next periodic interrupt. This function will attempt
- * to schedule a periodic interrupt later if necessary. If the scheduling
- * of an interrupt fails then the time to skip is lengthened
- * exponentially in order to ensure that the next interrupt
- * can be properly scheduled..
- */
-static int inline reschedule_periodic_timer(mmtimer_t *x)
-{
-       int n;
-       struct k_itimer *t = x->timer;
-
-       t->it.mmtimer.clock = x->i;
-       t->it_overrun--;
-
-       n = 0;
-       do {
-
-               t->it.mmtimer.expires += t->it.mmtimer.incr << n;
-               t->it_overrun += 1 << n;
-               n++;
-               if (n > 20)
-                       return 1;
-
-       } while (!mmtimer_setup(x->i, t->it.mmtimer.expires));
-
-       return 0;
-}
-
 /**
  * mmtimer_interrupt - timer interrupt handler
  * @irq: irq received
@@ -435,71 +512,75 @@ static int inline reschedule_periodic_timer(mmtimer_t *x)
 static irqreturn_t
 mmtimer_interrupt(int irq, void *dev_id)
 {
-       int i;
        unsigned long expires = 0;
        int result = IRQ_NONE;
        unsigned indx = cpu_to_node(smp_processor_id());
+       struct mmtimer *base;
 
-       /*
-        * Do this once for each comparison register
-        */
-       for (i = 0; i < NUM_COMPARATORS; i++) {
-               mmtimer_t *base = timers[indx] + i;
-               /* Make sure this doesn't get reused before tasklet_sched */
-               spin_lock(&base->lock);
-               if (base->cpu == smp_processor_id()) {
-                       if (base->timer)
-                               expires = base->timer->it.mmtimer.expires;
-                       /* expires test won't work with shared irqs */
-                       if ((mmtimer_int_pending(i) > 0) ||
-                               (expires && (expires < rtc_time()))) {
-                               mmtimer_clr_int_pending(i);
-                               tasklet_schedule(&base->tasklet);
-                               result = IRQ_HANDLED;
-                       }
+       spin_lock(&timers[indx].lock);
+       base = rb_entry(timers[indx].next, struct mmtimer, list);
+       if (base == NULL) {
+               spin_unlock(&timers[indx].lock);
+               return result;
+       }
+
+       if (base->cpu == smp_processor_id()) {
+               if (base->timer)
+                       expires = base->timer->it.mmtimer.expires;
+               /* expires test won't work with shared irqs */
+               if ((mmtimer_int_pending(COMPARATOR) > 0) ||
+                       (expires && (expires <= rtc_time()))) {
+                       mmtimer_clr_int_pending(COMPARATOR);
+                       tasklet_schedule(&timers[indx].tasklet);
+                       result = IRQ_HANDLED;
                }
-               spin_unlock(&base->lock);
-               expires = 0;
        }
+       spin_unlock(&timers[indx].lock);
        return result;
 }
 
-void mmtimer_tasklet(unsigned long data) {
-       mmtimer_t *x = (mmtimer_t *)data;
-       struct k_itimer *t = x->timer;
+static void mmtimer_tasklet(unsigned long data)
+{
+       int nodeid = data;
+       struct mmtimer_node *mn = &timers[nodeid];
+       struct mmtimer *x = rb_entry(mn->next, struct mmtimer, list);
+       struct k_itimer *t;
        unsigned long flags;
 
-       if (t == NULL)
-               return;
-
        /* Send signal and deal with periodic signals */
-       spin_lock_irqsave(&t->it_lock, flags);
-       spin_lock(&x->lock);
-       /* If timer was deleted between interrupt and here, leave */
-       if (t != x->timer)
+       spin_lock_irqsave(&mn->lock, flags);
+       if (!mn->next)
                goto out;
-       t->it_overrun = 0;
 
-       if (posix_timer_event(t, 0) != 0) {
+       x = rb_entry(mn->next, struct mmtimer, list);
+       t = x->timer;
+
+       if (t->it.mmtimer.clock == TIMER_OFF)
+               goto out;
+
+       t->it_overrun = 0;
 
-               // printk(KERN_WARNING "mmtimer: cannot deliver signal.\n");
+       mn->next = rb_next(&x->list);
+       rb_erase(&x->list, &mn->timer_head);
 
+       if (posix_timer_event(t, 0) != 0)
                t->it_overrun++;
-       }
+
        if(t->it.mmtimer.incr) {
-               /* Periodic timer */
-               if (reschedule_periodic_timer(x)) {
-                       printk(KERN_WARNING "mmtimer: unable to reschedule\n");
-                       x->timer = NULL;
-               }
+               t->it.mmtimer.expires += t->it.mmtimer.incr;
+               mmtimer_add_list(x);
        } else {
                /* Ensure we don't false trigger in mmtimer_interrupt */
+               t->it.mmtimer.clock = TIMER_OFF;
                t->it.mmtimer.expires = 0;
+               kfree(x);
        }
+       /* Set comparator for next timer, if there is one */
+       mmtimer_set_next_timer(nodeid);
+
        t->it_overrun_last = t->it_overrun;
 out:
-       spin_unlock(&x->lock);
-       spin_unlock_irqrestore(&t->it_lock, flags);
+       spin_unlock_irqrestore(&mn->lock, flags);
 }
 
 static int sgi_timer_create(struct k_itimer *timer)
@@ -516,19 +597,50 @@ static int sgi_timer_create(struct k_itimer *timer)
  */
 static int sgi_timer_del(struct k_itimer *timr)
 {
-       int i = timr->it.mmtimer.clock;
        cnodeid_t nodeid = timr->it.mmtimer.node;
-       mmtimer_t *t = timers[nodeid] + i;
        unsigned long irqflags;
 
-       if (i != TIMER_OFF) {
-               spin_lock_irqsave(&t->lock, irqflags);
-               mmtimer_disable_int(cnodeid_to_nasid(nodeid),i);
-               t->timer = NULL;
+       spin_lock_irqsave(&timers[nodeid].lock, irqflags);
+       if (timr->it.mmtimer.clock != TIMER_OFF) {
+               unsigned long expires = timr->it.mmtimer.expires;
+               struct rb_node *n = timers[nodeid].timer_head.rb_node;
+               struct mmtimer *uninitialized_var(t);
+               int r = 0;
+
                timr->it.mmtimer.clock = TIMER_OFF;
                timr->it.mmtimer.expires = 0;
-               spin_unlock_irqrestore(&t->lock, irqflags);
+
+               while (n) {
+                       t = rb_entry(n, struct mmtimer, list);
+                       if (t->timer == timr)
+                               break;
+
+                       if (expires < t->timer->it.mmtimer.expires)
+                               n = n->rb_left;
+                       else
+                               n = n->rb_right;
+               }
+
+               if (!n) {
+                       spin_unlock_irqrestore(&timers[nodeid].lock, irqflags);
+                       return 0;
+               }
+
+               if (timers[nodeid].next == n) {
+                       timers[nodeid].next = rb_next(n);
+                       r = 1;
+               }
+
+               rb_erase(n, &timers[nodeid].timer_head);
+               kfree(t);
+
+               if (r) {
+                       mmtimer_disable_int(cnodeid_to_nasid(nodeid),
+                               COMPARATOR);
+                       mmtimer_set_next_timer(nodeid);
+               }
        }
+       spin_unlock_irqrestore(&timers[nodeid].lock, irqflags);
        return 0;
 }
 
@@ -557,12 +669,11 @@ static int sgi_timer_set(struct k_itimer *timr, int flags,
        struct itimerspec * new_setting,
        struct itimerspec * old_setting)
 {
-
-       int i;
        unsigned long when, period, irqflags;
        int err = 0;
        cnodeid_t nodeid;
-       mmtimer_t *base;
+       struct mmtimer *base;
+       struct rb_node *n;
 
        if (old_setting)
                sgi_timer_get(timr, old_setting);
@@ -575,6 +686,10 @@ static int sgi_timer_set(struct k_itimer *timr, int flags,
                /* Clear timer */
                return 0;
 
+       base = kmalloc(sizeof(struct mmtimer), GFP_KERNEL);
+       if (base == NULL)
+               return -ENOMEM;
+
        if (flags & TIMER_ABSTIME) {
                struct timespec n;
                unsigned long now;
@@ -604,47 +719,38 @@ static int sgi_timer_set(struct k_itimer *timr, int flags,
        preempt_disable();
 
        nodeid =  cpu_to_node(smp_processor_id());
-retry:
-       /* Don't use an allocated timer, or a deleted one that's pending */
-       for(i = 0; i< NUM_COMPARATORS; i++) {
-               base = timers[nodeid] + i;
-               if (!base->timer && !base->tasklet.state) {
-                       break;
-               }
-       }
-
-       if (i == NUM_COMPARATORS) {
-               preempt_enable();
-               return -EBUSY;
-       }
 
-       spin_lock_irqsave(&base->lock, irqflags);
+       /* Lock the node timer structure */
+       spin_lock_irqsave(&timers[nodeid].lock, irqflags);
 
-       if (base->timer || base->tasklet.state != 0) {
-               spin_unlock_irqrestore(&base->lock, irqflags);
-               goto retry;
-       }
        base->timer = timr;
        base->cpu = smp_processor_id();
 
-       timr->it.mmtimer.clock = i;
+       timr->it.mmtimer.clock = TIMER_SET;
        timr->it.mmtimer.node = nodeid;
        timr->it.mmtimer.incr = period;
        timr->it.mmtimer.expires = when;
 
-       if (period == 0) {
-               if (!mmtimer_setup(i, when)) {
-                       mmtimer_disable_int(-1, i);
-                       posix_timer_event(timr, 0);
-                       timr->it.mmtimer.expires = 0;
-               }
-       } else {
-               timr->it.mmtimer.expires -= period;
-               if (reschedule_periodic_timer(base))
-                       err = -EINVAL;
+       n = timers[nodeid].next;
+
+       /* Add the new struct mmtimer to node's timer list */
+       mmtimer_add_list(base);
+
+       if (timers[nodeid].next == n) {
+               /* No need to reprogram comparator for now */
+               spin_unlock_irqrestore(&timers[nodeid].lock, irqflags);
+               preempt_enable();
+               return err;
        }
 
-       spin_unlock_irqrestore(&base->lock, irqflags);
+       /* We need to reprogram the comparator */
+       if (n)
+               mmtimer_disable_int(cnodeid_to_nasid(nodeid), COMPARATOR);
+
+       mmtimer_set_next_timer(nodeid);
+
+       /* Unlock the node timer structure */
+       spin_unlock_irqrestore(&timers[nodeid].lock, irqflags);
 
        preempt_enable();
 
@@ -669,7 +775,6 @@ static struct k_clock sgi_clock = {
  */
 static int __init mmtimer_init(void)
 {
-       unsigned i;
        cnodeid_t node, maxn = -1;
 
        if (!ia64_platform_is("sn2"))
@@ -706,31 +811,18 @@ static int __init mmtimer_init(void)
        maxn++;
 
        /* Allocate list of node ptrs to mmtimer_t's */
-       timers = kzalloc(sizeof(mmtimer_t *)*maxn, GFP_KERNEL);
+       timers = kzalloc(sizeof(struct mmtimer_node)*maxn, GFP_KERNEL);
        if (timers == NULL) {
                printk(KERN_ERR "%s: failed to allocate memory for device\n",
                                MMTIMER_NAME);
                goto out3;
        }
 
-       /* Allocate mmtimer_t's for each online node */
+       /* Initialize struct mmtimer's for each online node */
        for_each_online_node(node) {
-               timers[node] = kmalloc_node(sizeof(mmtimer_t)*NUM_COMPARATORS, GFP_KERNEL, node);
-               if (timers[node] == NULL) {
-                       printk(KERN_ERR "%s: failed to allocate memory for device\n",
-                               MMTIMER_NAME);
-                       goto out4;
-               }
-               for (i=0; i< NUM_COMPARATORS; i++) {
-                       mmtimer_t * base = timers[node] + i;
-
-                       spin_lock_init(&base->lock);
-                       base->timer = NULL;
-                       base->cpu = 0;
-                       base->i = i;
-                       tasklet_init(&base->tasklet, mmtimer_tasklet,
-                               (unsigned long) (base));
-               }
+               spin_lock_init(&timers[node].lock);
+               tasklet_init(&timers[node].tasklet, mmtimer_tasklet,
+                       (unsigned long) node);
        }
 
        sgi_clock_period = sgi_clock.res = NSEC_PER_SEC / sn_rtc_cycles_per_second;
@@ -741,11 +833,8 @@ static int __init mmtimer_init(void)
 
        return 0;
 
-out4:
-       for_each_online_node(node) {
-               kfree(timers[node]);
-       }
 out3:
+       kfree(timers);
        misc_deregister(&mmtimer_miscdev);
 out2:
        free_irq(SGI_MMTIMER_VECTOR, NULL);
@@ -754,4 +843,3 @@ out1:
 }
 
 module_init(mmtimer_init);
-
index 64b7b2b18352526d92e0ebf83f6bda424aed7d1c..d57d3a61919b310f22e972e97cf1c8797334db1d 100644 (file)
@@ -2,7 +2,8 @@
 /*
  *           moxa.c  -- MOXA Intellio family multiport serial driver.
  *
- *      Copyright (C) 1999-2000  Moxa Technologies (support@moxa.com.tw).
+ *      Copyright (C) 1999-2000  Moxa Technologies (support@moxa.com).
+ *      Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
  *
  *      This code is loosely based on the Linux serial driver, written by
  *      Linus Torvalds, Theodore T'so and others.
@@ -25,6 +26,7 @@
 #include <linux/mm.h>
 #include <linux/ioport.h>
 #include <linux/errno.h>
+#include <linux/firmware.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
-#include <linux/completion.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
-#define MOXA_VERSION           "5.1k"
+#include "moxa.h"
+
+#define MOXA_VERSION           "6.0k"
+
+#define MOXA_FW_HDRLEN         32
 
 #define MOXAMAJOR              172
-#define MOXACUMAJOR            173
 
 #define MAX_BOARDS             4       /* Don't change this value */
 #define MAX_PORTS_PER_BOARD    32      /* Don't change this value */
 #define MAX_PORTS              (MAX_BOARDS * MAX_PORTS_PER_BOARD)
 
+#define MOXA_IS_320(brd) ((brd)->boardType == MOXA_BOARD_C320_ISA || \
+               (brd)->boardType == MOXA_BOARD_C320_PCI)
+
 /*
  *    Define the Moxa PCI vendor and device IDs.
  */
@@ -92,24 +99,16 @@ static struct pci_device_id moxa_pcibrds[] = {
 MODULE_DEVICE_TABLE(pci, moxa_pcibrds);
 #endif /* CONFIG_PCI */
 
-struct moxa_isa_board_conf {
-       int boardType;
-       int numPorts;
-       unsigned long baseAddr;
-};
-
-static struct moxa_isa_board_conf moxa_isa_boards[] =
-{
-/*       {MOXA_BOARD_C218_ISA,8,0xDC000}, */
-};
+struct moxa_port;
 
 static struct moxa_board_conf {
        int boardType;
        int numPorts;
-       unsigned long baseAddr;
        int busType;
 
-       int loadstat;
+       unsigned int ready;
+
+       struct moxa_port *ports;
 
        void __iomem *basemem;
        void __iomem *intNdx;
@@ -131,30 +130,27 @@ struct moxaq_str {
 };
 
 struct moxa_port {
+       struct moxa_board_conf *board;
+       struct tty_struct *tty;
+       void __iomem *tableAddr;
+
        int type;
-       int port;
        int close_delay;
-       unsigned short closing_wait;
-       int count;
-       int blocked_open;
-       long event; /* long req'd for set_bit --RR */
+       unsigned int count;
        int asyncflags;
-       unsigned long statusflags;
-       struct tty_struct *tty;
        int cflag;
+       unsigned long statusflags;
        wait_queue_head_t open_wait;
-       struct completion close_wait;
 
-       struct timer_list emptyTimer;
-
-       char chkPort;
-       char lineCtrl;
-       void __iomem *tableAddr;
-       long curBaud;
-       char DCDState;
-       char lowChkFlag;
+       u8 DCDState;
+       u8 lineCtrl;
+       u8 lowChkFlag;
+};
 
-       ushort breakCnt;
+struct mon_str {
+       int tick;
+       int rxcnt[MAX_PORTS];
+       int txcnt[MAX_PORTS];
 };
 
 /* statusflags */
@@ -168,20 +164,27 @@ struct moxa_port {
 #define WAKEUP_CHARS           256
 
 static int ttymajor = MOXAMAJOR;
+static struct mon_str moxaLog;
+static unsigned int moxaFuncTout = HZ / 2;
+static unsigned int moxaLowWaterChk;
+static DEFINE_MUTEX(moxa_openlock);
 /* Variables for insmod */
 #ifdef MODULE
-static int baseaddr[4];
-static int type[4];
-static int numports[4];
+static unsigned long baseaddr[MAX_BOARDS];
+static unsigned int type[MAX_BOARDS];
+static unsigned int numports[MAX_BOARDS];
 #endif
 
 MODULE_AUTHOR("William Chen");
 MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver");
 MODULE_LICENSE("GPL");
 #ifdef MODULE
-module_param_array(type, int, NULL, 0);
-module_param_array(baseaddr, int, NULL, 0);
-module_param_array(numports, int, NULL, 0);
+module_param_array(type, uint, NULL, 0);
+MODULE_PARM_DESC(type, "card type: C218=2, C320=4");
+module_param_array(baseaddr, ulong, NULL, 0);
+MODULE_PARM_DESC(baseaddr, "base address");
+module_param_array(numports, uint, NULL, 0);
+MODULE_PARM_DESC(numports, "numports (ignored for C218)");
 #endif
 module_param(ttymajor, int, 0);
 
@@ -194,9 +197,6 @@ static int moxa_write(struct tty_struct *, const unsigned char *, int);
 static int moxa_write_room(struct tty_struct *);
 static void moxa_flush_buffer(struct tty_struct *);
 static int moxa_chars_in_buffer(struct tty_struct *);
-static void moxa_flush_chars(struct tty_struct *);
-static void moxa_put_char(struct tty_struct *, unsigned char);
-static int moxa_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long);
 static void moxa_throttle(struct tty_struct *);
 static void moxa_unthrottle(struct tty_struct *);
 static void moxa_set_termios(struct tty_struct *, struct ktermios *);
@@ -208,44 +208,183 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
                         unsigned int set, unsigned int clear);
 static void moxa_poll(unsigned long);
 static void moxa_set_tty_param(struct tty_struct *, struct ktermios *);
-static int moxa_block_till_ready(struct tty_struct *, struct file *,
-                           struct moxa_port *);
 static void moxa_setup_empty_event(struct tty_struct *);
-static void moxa_check_xmit_empty(unsigned long);
 static void moxa_shut_down(struct moxa_port *);
-static void moxa_receive_data(struct moxa_port *);
 /*
  * moxa board interface functions:
  */
-static void MoxaDriverInit(void);
-static int MoxaDriverIoctl(unsigned int, unsigned long, int);
-static int MoxaDriverPoll(void);
-static int MoxaPortsOfCard(int);
-static int MoxaPortIsValid(int);
-static void MoxaPortEnable(int);
-static void MoxaPortDisable(int);
-static long MoxaPortGetMaxBaud(int);
-static long MoxaPortSetBaud(int, long);
-static int MoxaPortSetTermio(int, struct ktermios *, speed_t);
-static int MoxaPortGetLineOut(int, int *, int *);
-static void MoxaPortLineCtrl(int, int, int);
-static void MoxaPortFlowCtrl(int, int, int, int, int, int);
-static int MoxaPortLineStatus(int);
-static int MoxaPortDCDChange(int);
-static int MoxaPortDCDON(int);
-static void MoxaPortFlushData(int, int);
-static int MoxaPortWriteData(int, unsigned char *, int);
-static int MoxaPortReadData(int, struct tty_struct *tty);
-static int MoxaPortTxQueue(int);
-static int MoxaPortRxQueue(int);
-static int MoxaPortTxFree(int);
-static void MoxaPortTxDisable(int);
-static void MoxaPortTxEnable(int);
-static int MoxaPortResetBrkCnt(int);
-static void MoxaPortSendBreak(int, int);
+static void MoxaPortEnable(struct moxa_port *);
+static void MoxaPortDisable(struct moxa_port *);
+static int MoxaPortSetTermio(struct moxa_port *, struct ktermios *, speed_t);
+static int MoxaPortGetLineOut(struct moxa_port *, int *, int *);
+static void MoxaPortLineCtrl(struct moxa_port *, int, int);
+static void MoxaPortFlowCtrl(struct moxa_port *, int, int, int, int, int);
+static int MoxaPortLineStatus(struct moxa_port *);
+static void MoxaPortFlushData(struct moxa_port *, int);
+static int MoxaPortWriteData(struct moxa_port *, const unsigned char *, int);
+static int MoxaPortReadData(struct moxa_port *);
+static int MoxaPortTxQueue(struct moxa_port *);
+static int MoxaPortRxQueue(struct moxa_port *);
+static int MoxaPortTxFree(struct moxa_port *);
+static void MoxaPortTxDisable(struct moxa_port *);
+static void MoxaPortTxEnable(struct moxa_port *);
 static int moxa_get_serial_info(struct moxa_port *, struct serial_struct __user *);
 static int moxa_set_serial_info(struct moxa_port *, struct serial_struct __user *);
-static void MoxaSetFifo(int port, int enable);
+static void MoxaSetFifo(struct moxa_port *port, int enable);
+
+/*
+ * I/O functions
+ */
+
+static void moxa_wait_finish(void __iomem *ofsAddr)
+{
+       unsigned long end = jiffies + moxaFuncTout;
+
+       while (readw(ofsAddr + FuncCode) != 0)
+               if (time_after(jiffies, end))
+                       return;
+       if (readw(ofsAddr + FuncCode) != 0 && printk_ratelimit())
+               printk(KERN_WARNING "moxa function expired\n");
+}
+
+static void moxafunc(void __iomem *ofsAddr, u16 cmd, u16 arg)
+{
+       writew(arg, ofsAddr + FuncArg);
+       writew(cmd, ofsAddr + FuncCode);
+       moxa_wait_finish(ofsAddr);
+}
+
+static void moxa_low_water_check(void __iomem *ofsAddr)
+{
+       u16 rptr, wptr, mask, len;
+
+       if (readb(ofsAddr + FlagStat) & Xoff_state) {
+               rptr = readw(ofsAddr + RXrptr);
+               wptr = readw(ofsAddr + RXwptr);
+               mask = readw(ofsAddr + RX_mask);
+               len = (wptr - rptr) & mask;
+               if (len <= Low_water)
+                       moxafunc(ofsAddr, FC_SendXon, 0);
+       }
+}
+
+/*
+ * TTY operations
+ */
+
+static int moxa_ioctl(struct tty_struct *tty, struct file *file,
+                     unsigned int cmd, unsigned long arg)
+{
+       struct moxa_port *ch = tty->driver_data;
+       void __user *argp = (void __user *)arg;
+       int status, ret = 0;
+
+       if (tty->index == MAX_PORTS) {
+               if (cmd != MOXA_GETDATACOUNT && cmd != MOXA_GET_IOQUEUE &&
+                               cmd != MOXA_GETMSTATUS)
+                       return -EINVAL;
+       } else if (!ch)
+               return -ENODEV;
+
+       switch (cmd) {
+       case MOXA_GETDATACOUNT:
+               moxaLog.tick = jiffies;
+               if (copy_to_user(argp, &moxaLog, sizeof(moxaLog)))
+                       ret = -EFAULT;
+               break;
+       case MOXA_FLUSH_QUEUE:
+               MoxaPortFlushData(ch, arg);
+               break;
+       case MOXA_GET_IOQUEUE: {
+               struct moxaq_str __user *argm = argp;
+               struct moxaq_str tmp;
+               struct moxa_port *p;
+               unsigned int i, j;
+
+               mutex_lock(&moxa_openlock);
+               for (i = 0; i < MAX_BOARDS; i++) {
+                       p = moxa_boards[i].ports;
+                       for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
+                               memset(&tmp, 0, sizeof(tmp));
+                               if (moxa_boards[i].ready) {
+                                       tmp.inq = MoxaPortRxQueue(p);
+                                       tmp.outq = MoxaPortTxQueue(p);
+                               }
+                               if (copy_to_user(argm, &tmp, sizeof(tmp))) {
+                                       mutex_unlock(&moxa_openlock);
+                                       return -EFAULT;
+                               }
+                       }
+               }
+               mutex_unlock(&moxa_openlock);
+               break;
+       } case MOXA_GET_OQUEUE:
+               status = MoxaPortTxQueue(ch);
+               ret = put_user(status, (unsigned long __user *)argp);
+               break;
+       case MOXA_GET_IQUEUE:
+               status = MoxaPortRxQueue(ch);
+               ret = put_user(status, (unsigned long __user *)argp);
+               break;
+       case MOXA_GETMSTATUS: {
+               struct mxser_mstatus __user *argm = argp;
+               struct mxser_mstatus tmp;
+               struct moxa_port *p;
+               unsigned int i, j;
+
+               mutex_lock(&moxa_openlock);
+               for (i = 0; i < MAX_BOARDS; i++) {
+                       p = moxa_boards[i].ports;
+                       for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
+                               memset(&tmp, 0, sizeof(tmp));
+                               if (!moxa_boards[i].ready)
+                                       goto copy;
+
+                               status = MoxaPortLineStatus(p);
+                               if (status & 1)
+                                       tmp.cts = 1;
+                               if (status & 2)
+                                       tmp.dsr = 1;
+                               if (status & 4)
+                                       tmp.dcd = 1;
+
+                               if (!p->tty || !p->tty->termios)
+                                       tmp.cflag = p->cflag;
+                               else
+                                       tmp.cflag = p->tty->termios->c_cflag;
+copy:
+                               if (copy_to_user(argm, &tmp, sizeof(tmp))) {
+                                       mutex_unlock(&moxa_openlock);
+                                       return -EFAULT;
+                               }
+                       }
+               }
+               mutex_unlock(&moxa_openlock);
+               break;
+       }
+       case TIOCGSERIAL:
+               mutex_lock(&moxa_openlock);
+               ret = moxa_get_serial_info(ch, argp);
+               mutex_unlock(&moxa_openlock);
+               break;
+       case TIOCSSERIAL:
+               mutex_lock(&moxa_openlock);
+               ret = moxa_set_serial_info(ch, argp);
+               mutex_unlock(&moxa_openlock);
+               break;
+       default:
+               ret = -ENOIOCTLCMD;
+       }
+       return ret;
+}
+
+static void moxa_break_ctl(struct tty_struct *tty, int state)
+{
+       struct moxa_port *port = tty->driver_data;
+
+       moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak,
+                       Magic_code);
+}
 
 static const struct tty_operations moxa_ops = {
        .open = moxa_open,
@@ -254,8 +393,6 @@ static const struct tty_operations moxa_ops = {
        .write_room = moxa_write_room,
        .flush_buffer = moxa_flush_buffer,
        .chars_in_buffer = moxa_chars_in_buffer,
-       .flush_chars = moxa_flush_chars,
-       .put_char = moxa_put_char,
        .ioctl = moxa_ioctl,
        .throttle = moxa_throttle,
        .unthrottle = moxa_unthrottle,
@@ -263,259 +400,795 @@ static const struct tty_operations moxa_ops = {
        .stop = moxa_stop,
        .start = moxa_start,
        .hangup = moxa_hangup,
+       .break_ctl = moxa_break_ctl,
        .tiocmget = moxa_tiocmget,
        .tiocmset = moxa_tiocmset,
 };
 
 static struct tty_driver *moxaDriver;
-static struct moxa_port moxa_ports[MAX_PORTS];
 static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0);
 static DEFINE_SPINLOCK(moxa_lock);
 
-#ifdef CONFIG_PCI
-static int __devinit moxa_pci_probe(struct pci_dev *pdev,
-               const struct pci_device_id *ent)
-{
-       struct moxa_board_conf *board;
-       unsigned int i;
-       int board_type = ent->driver_data;
-       int retval;
-
-       retval = pci_enable_device(pdev);
-       if (retval) {
-               dev_err(&pdev->dev, "can't enable pci device\n");
-               goto err;
-       }
-
-       for (i = 0; i < MAX_BOARDS; i++)
-               if (moxa_boards[i].basemem == NULL)
-                       break;
-
-       retval = -ENODEV;
-       if (i >= MAX_BOARDS) {
-               dev_warn(&pdev->dev, "more than %u MOXA Intellio family boards "
-                               "found. Board is ignored.\n", MAX_BOARDS);
-               goto err;
-       }
-
-       board = &moxa_boards[i];
-       board->basemem = pci_iomap(pdev, 2, 0x4000);
-       if (board->basemem == NULL) {
-               dev_err(&pdev->dev, "can't remap io space 2\n");
-               goto err;
-       }
+/*
+ * HW init
+ */
 
-       board->boardType = board_type;
-       switch (board_type) {
+static int moxa_check_fw_model(struct moxa_board_conf *brd, u8 model)
+{
+       switch (brd->boardType) {
        case MOXA_BOARD_C218_ISA:
        case MOXA_BOARD_C218_PCI:
-               board->numPorts = 8;
+               if (model != 1)
+                       goto err;
                break;
-
        case MOXA_BOARD_CP204J:
-               board->numPorts = 4;
+               if (model != 3)
+                       goto err;
                break;
        default:
-               board->numPorts = 0;
+               if (model != 2)
+                       goto err;
                break;
        }
-       board->busType = MOXA_BUS_TYPE_PCI;
-
-       pci_set_drvdata(pdev, board);
-
-       return (0);
+       return 0;
 err:
-       return retval;
+       return -EINVAL;
 }
 
-static void __devexit moxa_pci_remove(struct pci_dev *pdev)
+static int moxa_check_fw(const void *ptr)
 {
-       struct moxa_board_conf *brd = pci_get_drvdata(pdev);
+       const __le16 *lptr = ptr;
 
-       pci_iounmap(pdev, brd->basemem);
-       brd->basemem = NULL;
-}
+       if (*lptr != cpu_to_le16(0x7980))
+               return -EINVAL;
 
-static struct pci_driver moxa_pci_driver = {
-       .name = "moxa",
-       .id_table = moxa_pcibrds,
-       .probe = moxa_pci_probe,
-       .remove = __devexit_p(moxa_pci_remove)
-};
-#endif /* CONFIG_PCI */
+       return 0;
+}
 
-static int __init moxa_init(void)
+static int moxa_load_bios(struct moxa_board_conf *brd, const u8 *buf,
+               size_t len)
 {
-       int i, numBoards, retval = 0;
-       struct moxa_port *ch;
-
-       printk(KERN_INFO "MOXA Intellio family driver version %s\n",
-                       MOXA_VERSION);
-       moxaDriver = alloc_tty_driver(MAX_PORTS + 1);
-       if (!moxaDriver)
-               return -ENOMEM;
-
-       moxaDriver->owner = THIS_MODULE;
-       moxaDriver->name = "ttyMX";
-       moxaDriver->major = ttymajor;
-       moxaDriver->minor_start = 0;
-       moxaDriver->type = TTY_DRIVER_TYPE_SERIAL;
-       moxaDriver->subtype = SERIAL_TYPE_NORMAL;
-       moxaDriver->init_termios = tty_std_termios;
-       moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
-       moxaDriver->init_termios.c_ispeed = 9600;
-       moxaDriver->init_termios.c_ospeed = 9600;
-       moxaDriver->flags = TTY_DRIVER_REAL_RAW;
-       tty_set_operations(moxaDriver, &moxa_ops);
+       void __iomem *baseAddr = brd->basemem;
+       u16 tmp;
 
-       for (i = 0, ch = moxa_ports; i < MAX_PORTS; i++, ch++) {
-               ch->type = PORT_16550A;
-               ch->port = i;
-               ch->close_delay = 5 * HZ / 10;
-               ch->closing_wait = 30 * HZ;
-               ch->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
-               init_waitqueue_head(&ch->open_wait);
-               init_completion(&ch->close_wait);
-
-               setup_timer(&ch->emptyTimer, moxa_check_xmit_empty,
-                               (unsigned long)ch);
-       }
+       writeb(HW_reset, baseAddr + Control_reg);       /* reset */
+       msleep(10);
+       memset_io(baseAddr, 0, 4096);
+       memcpy_toio(baseAddr, buf, len);        /* download BIOS */
+       writeb(0, baseAddr + Control_reg);      /* restart */
 
-       pr_debug("Moxa tty devices major number = %d\n", ttymajor);
+       msleep(2000);
 
-       if (tty_register_driver(moxaDriver)) {
-               printk(KERN_ERR "Couldn't install MOXA Smartio family driver !\n");
-               put_tty_driver(moxaDriver);
-               return -1;
+       switch (brd->boardType) {
+       case MOXA_BOARD_C218_ISA:
+       case MOXA_BOARD_C218_PCI:
+               tmp = readw(baseAddr + C218_key);
+               if (tmp != C218_KeyCode)
+                       goto err;
+               break;
+       case MOXA_BOARD_CP204J:
+               tmp = readw(baseAddr + C218_key);
+               if (tmp != CP204J_KeyCode)
+                       goto err;
+               break;
+       default:
+               tmp = readw(baseAddr + C320_key);
+               if (tmp != C320_KeyCode)
+                       goto err;
+               tmp = readw(baseAddr + C320_status);
+               if (tmp != STS_init) {
+                       printk(KERN_ERR "MOXA: bios upload failed -- CPU/Basic "
+                                       "module not found\n");
+                       return -EIO;
+               }
+               break;
        }
 
-       mod_timer(&moxaTimer, jiffies + HZ / 50);
+       return 0;
+err:
+       printk(KERN_ERR "MOXA: bios upload failed -- board not found\n");
+       return -EIO;
+}
 
-       /* Find the boards defined in source code */
-       numBoards = 0;
-       for (i = 0; i < MAX_BOARDS; i++) {
-               if ((moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA) ||
-                (moxa_isa_boards[i].boardType == MOXA_BOARD_C320_ISA)) {
-                       moxa_boards[numBoards].boardType = moxa_isa_boards[i].boardType;
-                       if (moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA)
-                               moxa_boards[numBoards].numPorts = 8;
-                       else
-                               moxa_boards[numBoards].numPorts = moxa_isa_boards[i].numPorts;
-                       moxa_boards[numBoards].busType = MOXA_BUS_TYPE_ISA;
-                       moxa_boards[numBoards].baseAddr = moxa_isa_boards[i].baseAddr;
-                       pr_debug("Moxa board %2d: %s board(baseAddr=%lx)\n",
-                              numBoards + 1,
-                              moxa_brdname[moxa_boards[numBoards].boardType-1],
-                              moxa_boards[numBoards].baseAddr);
-                       numBoards++;
-               }
-       }
-       /* Find the boards defined form module args. */
-#ifdef MODULE
-       for (i = 0; i < MAX_BOARDS; i++) {
-               if ((type[i] == MOXA_BOARD_C218_ISA) ||
-                   (type[i] == MOXA_BOARD_C320_ISA)) {
-                       pr_debug("Moxa board %2d: %s board(baseAddr=%lx)\n",
-                              numBoards + 1, moxa_brdname[type[i] - 1],
-                              (unsigned long)baseaddr[i]);
-                       if (numBoards >= MAX_BOARDS) {
-                               printk(KERN_WARNING "More than %d MOXA "
-                                       "Intellio family boards found. Board "
-                                       "is ignored.\n", MAX_BOARDS);
-                               continue;
-                       }
-                       moxa_boards[numBoards].boardType = type[i];
-                       if (moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA)
-                               moxa_boards[numBoards].numPorts = 8;
-                       else
-                               moxa_boards[numBoards].numPorts = numports[i];
-                       moxa_boards[numBoards].busType = MOXA_BUS_TYPE_ISA;
-                       moxa_boards[numBoards].baseAddr = baseaddr[i];
-                       numBoards++;
-               }
-       }
-#endif
+static int moxa_load_320b(struct moxa_board_conf *brd, const u8 *ptr,
+               size_t len)
+{
+       void __iomem *baseAddr = brd->basemem;
 
-#ifdef CONFIG_PCI
-       retval = pci_register_driver(&moxa_pci_driver);
-       if (retval) {
-               printk(KERN_ERR "Can't register moxa pci driver!\n");
-               if (numBoards)
-                       retval = 0;
+       if (len < 7168) {
+               printk(KERN_ERR "MOXA: invalid 320 bios -- too short\n");
+               return -EINVAL;
        }
-#endif
 
-       for (i = 0; i < numBoards; i++) {
-               moxa_boards[i].basemem = ioremap(moxa_boards[i].baseAddr,
-                               0x4000);
-       }
+       writew(len - 7168 - 2, baseAddr + C320bapi_len);
+       writeb(1, baseAddr + Control_reg);      /* Select Page 1 */
+       memcpy_toio(baseAddr + DynPage_addr, ptr, 7168);
+       writeb(2, baseAddr + Control_reg);      /* Select Page 2 */
+       memcpy_toio(baseAddr + DynPage_addr, ptr + 7168, len - 7168);
 
-       return retval;
+       return 0;
 }
 
-static void __exit moxa_exit(void)
+static int moxa_real_load_code(struct moxa_board_conf *brd, const void *ptr,
+               size_t len)
 {
-       int i;
-
-       del_timer_sync(&moxaTimer);
+       void __iomem *baseAddr = brd->basemem;
+       const u16 *uptr = ptr;
+       size_t wlen, len2, j;
+       unsigned long key, loadbuf, loadlen, checksum, checksum_ok;
+       unsigned int i, retry;
+       u16 usum, keycode;
 
-       for (i = 0; i < MAX_PORTS; i++)
-               del_timer_sync(&moxa_ports[i].emptyTimer);
+       keycode = (brd->boardType == MOXA_BOARD_CP204J) ? CP204J_KeyCode :
+                               C218_KeyCode;
 
-       if (tty_unregister_driver(moxaDriver))
-               printk(KERN_ERR "Couldn't unregister MOXA Intellio family "
-                               "serial driver\n");
-       put_tty_driver(moxaDriver);
+       switch (brd->boardType) {
+       case MOXA_BOARD_CP204J:
+       case MOXA_BOARD_C218_ISA:
+       case MOXA_BOARD_C218_PCI:
+               key = C218_key;
+               loadbuf = C218_LoadBuf;
+               loadlen = C218DLoad_len;
+               checksum = C218check_sum;
+               checksum_ok = C218chksum_ok;
+               break;
+       default:
+               key = C320_key;
+               keycode = C320_KeyCode;
+               loadbuf = C320_LoadBuf;
+               loadlen = C320DLoad_len;
+               checksum = C320check_sum;
+               checksum_ok = C320chksum_ok;
+               break;
+       }
 
-#ifdef CONFIG_PCI
-       pci_unregister_driver(&moxa_pci_driver);
-#endif
+       usum = 0;
+       wlen = len >> 1;
+       for (i = 0; i < wlen; i++)
+               usum += le16_to_cpu(uptr[i]);
+       retry = 0;
+       do {
+               wlen = len >> 1;
+               j = 0;
+               while (wlen) {
+                       len2 = (wlen > 2048) ? 2048 : wlen;
+                       wlen -= len2;
+                       memcpy_toio(baseAddr + loadbuf, ptr + j, len2 << 1);
+                       j += len2 << 1;
+
+                       writew(len2, baseAddr + loadlen);
+                       writew(0, baseAddr + key);
+                       for (i = 0; i < 100; i++) {
+                               if (readw(baseAddr + key) == keycode)
+                                       break;
+                               msleep(10);
+                       }
+                       if (readw(baseAddr + key) != keycode)
+                               return -EIO;
+               }
+               writew(0, baseAddr + loadlen);
+               writew(usum, baseAddr + checksum);
+               writew(0, baseAddr + key);
+               for (i = 0; i < 100; i++) {
+                       if (readw(baseAddr + key) == keycode)
+                               break;
+                       msleep(10);
+               }
+               retry++;
+       } while ((readb(baseAddr + checksum_ok) != 1) && (retry < 3));
+       if (readb(baseAddr + checksum_ok) != 1)
+               return -EIO;
+
+       writew(0, baseAddr + key);
+       for (i = 0; i < 600; i++) {
+               if (readw(baseAddr + Magic_no) == Magic_code)
+                       break;
+               msleep(10);
+       }
+       if (readw(baseAddr + Magic_no) != Magic_code)
+               return -EIO;
+
+       if (MOXA_IS_320(brd)) {
+               if (brd->busType == MOXA_BUS_TYPE_PCI) {        /* ASIC board */
+                       writew(0x3800, baseAddr + TMS320_PORT1);
+                       writew(0x3900, baseAddr + TMS320_PORT2);
+                       writew(28499, baseAddr + TMS320_CLOCK);
+               } else {
+                       writew(0x3200, baseAddr + TMS320_PORT1);
+                       writew(0x3400, baseAddr + TMS320_PORT2);
+                       writew(19999, baseAddr + TMS320_CLOCK);
+               }
+       }
+       writew(1, baseAddr + Disable_IRQ);
+       writew(0, baseAddr + Magic_no);
+       for (i = 0; i < 500; i++) {
+               if (readw(baseAddr + Magic_no) == Magic_code)
+                       break;
+               msleep(10);
+       }
+       if (readw(baseAddr + Magic_no) != Magic_code)
+               return -EIO;
+
+       if (MOXA_IS_320(brd)) {
+               j = readw(baseAddr + Module_cnt);
+               if (j <= 0)
+                       return -EIO;
+               brd->numPorts = j * 8;
+               writew(j, baseAddr + Module_no);
+               writew(0, baseAddr + Magic_no);
+               for (i = 0; i < 600; i++) {
+                       if (readw(baseAddr + Magic_no) == Magic_code)
+                               break;
+                       msleep(10);
+               }
+               if (readw(baseAddr + Magic_no) != Magic_code)
+                       return -EIO;
+       }
+       brd->intNdx = baseAddr + IRQindex;
+       brd->intPend = baseAddr + IRQpending;
+       brd->intTable = baseAddr + IRQtable;
+
+       return 0;
+}
+
+static int moxa_load_code(struct moxa_board_conf *brd, const void *ptr,
+               size_t len)
+{
+       void __iomem *ofsAddr, *baseAddr = brd->basemem;
+       struct moxa_port *port;
+       int retval, i;
+
+       if (len % 2) {
+               printk(KERN_ERR "MOXA: bios length is not even\n");
+               return -EINVAL;
+       }
+
+       retval = moxa_real_load_code(brd, ptr, len); /* may change numPorts */
+       if (retval)
+               return retval;
+
+       switch (brd->boardType) {
+       case MOXA_BOARD_C218_ISA:
+       case MOXA_BOARD_C218_PCI:
+       case MOXA_BOARD_CP204J:
+               port = brd->ports;
+               for (i = 0; i < brd->numPorts; i++, port++) {
+                       port->board = brd;
+                       port->DCDState = 0;
+                       port->tableAddr = baseAddr + Extern_table +
+                                       Extern_size * i;
+                       ofsAddr = port->tableAddr;
+                       writew(C218rx_mask, ofsAddr + RX_mask);
+                       writew(C218tx_mask, ofsAddr + TX_mask);
+                       writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb);
+                       writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb);
+
+                       writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb);
+                       writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb);
+
+               }
+               break;
+       default:
+               port = brd->ports;
+               for (i = 0; i < brd->numPorts; i++, port++) {
+                       port->board = brd;
+                       port->DCDState = 0;
+                       port->tableAddr = baseAddr + Extern_table +
+                                       Extern_size * i;
+                       ofsAddr = port->tableAddr;
+                       switch (brd->numPorts) {
+                       case 8:
+                               writew(C320p8rx_mask, ofsAddr + RX_mask);
+                               writew(C320p8tx_mask, ofsAddr + TX_mask);
+                               writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb);
+                               writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb);
+                               writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb);
+                               writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb);
+
+                               break;
+                       case 16:
+                               writew(C320p16rx_mask, ofsAddr + RX_mask);
+                               writew(C320p16tx_mask, ofsAddr + TX_mask);
+                               writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb);
+                               writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb);
+                               writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb);
+                               writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb);
+                               break;
+
+                       case 24:
+                               writew(C320p24rx_mask, ofsAddr + RX_mask);
+                               writew(C320p24tx_mask, ofsAddr + TX_mask);
+                               writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb);
+                               writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb);
+                               writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb);
+                               writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
+                               break;
+                       case 32:
+                               writew(C320p32rx_mask, ofsAddr + RX_mask);
+                               writew(C320p32tx_mask, ofsAddr + TX_mask);
+                               writew(C320p32tx_ofs, ofsAddr + Ofs_txb);
+                               writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb);
+                               writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb);
+                               writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb);
+                               writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
+                               break;
+                       }
+               }
+               break;
+       }
+       return 0;
+}
+
+static int moxa_load_fw(struct moxa_board_conf *brd, const struct firmware *fw)
+{
+       void *ptr = fw->data;
+       char rsn[64];
+       u16 lens[5];
+       size_t len;
+       unsigned int a, lenp, lencnt;
+       int ret = -EINVAL;
+       struct {
+               __le32 magic;   /* 0x34303430 */
+               u8 reserved1[2];
+               u8 type;        /* UNIX = 3 */
+               u8 model;       /* C218T=1, C320T=2, CP204=3 */
+               u8 reserved2[8];
+               __le16 len[5];
+       } *hdr = ptr;
+
+       BUILD_BUG_ON(ARRAY_SIZE(hdr->len) != ARRAY_SIZE(lens));
+
+       if (fw->size < MOXA_FW_HDRLEN) {
+               strcpy(rsn, "too short (even header won't fit)");
+               goto err;
+       }
+       if (hdr->magic != cpu_to_le32(0x30343034)) {
+               sprintf(rsn, "bad magic: %.8x", le32_to_cpu(hdr->magic));
+               goto err;
+       }
+       if (hdr->type != 3) {
+               sprintf(rsn, "not for linux, type is %u", hdr->type);
+               goto err;
+       }
+       if (moxa_check_fw_model(brd, hdr->model)) {
+               sprintf(rsn, "not for this card, model is %u", hdr->model);
+               goto err;
+       }
+
+       len = MOXA_FW_HDRLEN;
+       lencnt = hdr->model == 2 ? 5 : 3;
+       for (a = 0; a < ARRAY_SIZE(lens); a++) {
+               lens[a] = le16_to_cpu(hdr->len[a]);
+               if (lens[a] && len + lens[a] <= fw->size &&
+                               moxa_check_fw(&fw->data[len]))
+                       printk(KERN_WARNING "MOXA firmware: unexpected input "
+                               "at offset %u, but going on\n", (u32)len);
+               if (!lens[a] && a < lencnt) {
+                       sprintf(rsn, "too few entries in fw file");
+                       goto err;
+               }
+               len += lens[a];
+       }
+
+       if (len != fw->size) {
+               sprintf(rsn, "bad length: %u (should be %u)", (u32)fw->size,
+                               (u32)len);
+               goto err;
+       }
+
+       ptr += MOXA_FW_HDRLEN;
+       lenp = 0; /* bios */
+
+       strcpy(rsn, "read above");
+
+       ret = moxa_load_bios(brd, ptr, lens[lenp]);
+       if (ret)
+               goto err;
+
+       /* we skip the tty section (lens[1]), since we don't need it */
+       ptr += lens[lenp] + lens[lenp + 1];
+       lenp += 2; /* comm */
+
+       if (hdr->model == 2) {
+               ret = moxa_load_320b(brd, ptr, lens[lenp]);
+               if (ret)
+                       goto err;
+               /* skip another tty */
+               ptr += lens[lenp] + lens[lenp + 1];
+               lenp += 2;
+       }
+
+       ret = moxa_load_code(brd, ptr, lens[lenp]);
+       if (ret)
+               goto err;
+
+       return 0;
+err:
+       printk(KERN_ERR "firmware failed to load, reason: %s\n", rsn);
+       return ret;
+}
+
+static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev)
+{
+       const struct firmware *fw;
+       const char *file;
+       struct moxa_port *p;
+       unsigned int i;
+       int ret;
+
+       brd->ports = kcalloc(MAX_PORTS_PER_BOARD, sizeof(*brd->ports),
+                       GFP_KERNEL);
+       if (brd->ports == NULL) {
+               printk(KERN_ERR "cannot allocate memory for ports\n");
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       for (i = 0, p = brd->ports; i < MAX_PORTS_PER_BOARD; i++, p++) {
+               p->type = PORT_16550A;
+               p->close_delay = 5 * HZ / 10;
+               p->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
+               init_waitqueue_head(&p->open_wait);
+       }
+
+       switch (brd->boardType) {
+       case MOXA_BOARD_C218_ISA:
+       case MOXA_BOARD_C218_PCI:
+               file = "c218tunx.cod";
+               break;
+       case MOXA_BOARD_CP204J:
+               file = "cp204unx.cod";
+               break;
+       default:
+               file = "c320tunx.cod";
+               break;
+       }
+
+       ret = request_firmware(&fw, file, dev);
+       if (ret) {
+               printk(KERN_ERR "MOXA: request_firmware failed. Make sure "
+                               "you've placed '%s' file into your firmware "
+                               "loader directory (e.g. /lib/firmware)\n",
+                               file);
+               goto err_free;
+       }
+
+       ret = moxa_load_fw(brd, fw);
+
+       release_firmware(fw);
+
+       if (ret)
+               goto err_free;
+
+       spin_lock_bh(&moxa_lock);
+       brd->ready = 1;
+       if (!timer_pending(&moxaTimer))
+               mod_timer(&moxaTimer, jiffies + HZ / 50);
+       spin_unlock_bh(&moxa_lock);
+
+       return 0;
+err_free:
+       kfree(brd->ports);
+err:
+       return ret;
+}
+
+static void moxa_board_deinit(struct moxa_board_conf *brd)
+{
+       unsigned int a, opened;
+
+       mutex_lock(&moxa_openlock);
+       spin_lock_bh(&moxa_lock);
+       brd->ready = 0;
+       spin_unlock_bh(&moxa_lock);
+
+       /* pci hot-un-plug support */
+       for (a = 0; a < brd->numPorts; a++)
+               if (brd->ports[a].asyncflags & ASYNC_INITIALIZED)
+                       tty_hangup(brd->ports[a].tty);
+       while (1) {
+               opened = 0;
+               for (a = 0; a < brd->numPorts; a++)
+                       if (brd->ports[a].asyncflags & ASYNC_INITIALIZED)
+                               opened++;
+               mutex_unlock(&moxa_openlock);
+               if (!opened)
+                       break;
+               msleep(50);
+               mutex_lock(&moxa_openlock);
+       }
+
+       iounmap(brd->basemem);
+       brd->basemem = NULL;
+       kfree(brd->ports);
+}
+
+#ifdef CONFIG_PCI
+static int __devinit moxa_pci_probe(struct pci_dev *pdev,
+               const struct pci_device_id *ent)
+{
+       struct moxa_board_conf *board;
+       unsigned int i;
+       int board_type = ent->driver_data;
+       int retval;
+
+       retval = pci_enable_device(pdev);
+       if (retval) {
+               dev_err(&pdev->dev, "can't enable pci device\n");
+               goto err;
+       }
 
        for (i = 0; i < MAX_BOARDS; i++)
-               if (moxa_boards[i].basemem)
-                       iounmap(moxa_boards[i].basemem);
+               if (moxa_boards[i].basemem == NULL)
+                       break;
+
+       retval = -ENODEV;
+       if (i >= MAX_BOARDS) {
+               dev_warn(&pdev->dev, "more than %u MOXA Intellio family boards "
+                               "found. Board is ignored.\n", MAX_BOARDS);
+               goto err;
+       }
+
+       board = &moxa_boards[i];
+
+       retval = pci_request_region(pdev, 2, "moxa-base");
+       if (retval) {
+               dev_err(&pdev->dev, "can't request pci region 2\n");
+               goto err;
+       }
+
+       board->basemem = ioremap_nocache(pci_resource_start(pdev, 2), 0x4000);
+       if (board->basemem == NULL) {
+               dev_err(&pdev->dev, "can't remap io space 2\n");
+               goto err_reg;
+       }
+
+       board->boardType = board_type;
+       switch (board_type) {
+       case MOXA_BOARD_C218_ISA:
+       case MOXA_BOARD_C218_PCI:
+               board->numPorts = 8;
+               break;
+
+       case MOXA_BOARD_CP204J:
+               board->numPorts = 4;
+               break;
+       default:
+               board->numPorts = 0;
+               break;
+       }
+       board->busType = MOXA_BUS_TYPE_PCI;
+
+       retval = moxa_init_board(board, &pdev->dev);
+       if (retval)
+               goto err_base;
+
+       pci_set_drvdata(pdev, board);
+
+       dev_info(&pdev->dev, "board '%s' ready (%u ports, firmware loaded)\n",
+                       moxa_brdname[board_type - 1], board->numPorts);
+
+       return 0;
+err_base:
+       iounmap(board->basemem);
+       board->basemem = NULL;
+err_reg:
+       pci_release_region(pdev, 2);
+err:
+       return retval;
+}
+
+static void __devexit moxa_pci_remove(struct pci_dev *pdev)
+{
+       struct moxa_board_conf *brd = pci_get_drvdata(pdev);
+
+       moxa_board_deinit(brd);
+
+       pci_release_region(pdev, 2);
+}
+
+static struct pci_driver moxa_pci_driver = {
+       .name = "moxa",
+       .id_table = moxa_pcibrds,
+       .probe = moxa_pci_probe,
+       .remove = __devexit_p(moxa_pci_remove)
+};
+#endif /* CONFIG_PCI */
+
+static int __init moxa_init(void)
+{
+       unsigned int isabrds = 0;
+       int retval = 0;
+
+       printk(KERN_INFO "MOXA Intellio family driver version %s\n",
+                       MOXA_VERSION);
+       moxaDriver = alloc_tty_driver(MAX_PORTS + 1);
+       if (!moxaDriver)
+               return -ENOMEM;
+
+       moxaDriver->owner = THIS_MODULE;
+       moxaDriver->name = "ttyMX";
+       moxaDriver->major = ttymajor;
+       moxaDriver->minor_start = 0;
+       moxaDriver->type = TTY_DRIVER_TYPE_SERIAL;
+       moxaDriver->subtype = SERIAL_TYPE_NORMAL;
+       moxaDriver->init_termios = tty_std_termios;
+       moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
+       moxaDriver->init_termios.c_ispeed = 9600;
+       moxaDriver->init_termios.c_ospeed = 9600;
+       moxaDriver->flags = TTY_DRIVER_REAL_RAW;
+       tty_set_operations(moxaDriver, &moxa_ops);
+
+       if (tty_register_driver(moxaDriver)) {
+               printk(KERN_ERR "can't register MOXA Smartio tty driver!\n");
+               put_tty_driver(moxaDriver);
+               return -1;
+       }
+
+       /* Find the boards defined from module args. */
+#ifdef MODULE
+       {
+       struct moxa_board_conf *brd = moxa_boards;
+       unsigned int i;
+       for (i = 0; i < MAX_BOARDS; i++) {
+               if (!baseaddr[i])
+                       break;
+               if (type[i] == MOXA_BOARD_C218_ISA ||
+                               type[i] == MOXA_BOARD_C320_ISA) {
+                       pr_debug("Moxa board %2d: %s board(baseAddr=%lx)\n",
+                                       isabrds + 1, moxa_brdname[type[i] - 1],
+                                       baseaddr[i]);
+                       brd->boardType = type[i];
+                       brd->numPorts = type[i] == MOXA_BOARD_C218_ISA ? 8 :
+                                       numports[i];
+                       brd->busType = MOXA_BUS_TYPE_ISA;
+                       brd->basemem = ioremap_nocache(baseaddr[i], 0x4000);
+                       if (!brd->basemem) {
+                               printk(KERN_ERR "MOXA: can't remap %lx\n",
+                                               baseaddr[i]);
+                               continue;
+                       }
+                       if (moxa_init_board(brd, NULL)) {
+                               iounmap(brd->basemem);
+                               brd->basemem = NULL;
+                               continue;
+                       }
+
+                       printk(KERN_INFO "MOXA isa board found at 0x%.8lu and "
+                                       "ready (%u ports, firmware loaded)\n",
+                                       baseaddr[i], brd->numPorts);
+
+                       brd++;
+                       isabrds++;
+               }
+       }
+       }
+#endif
+
+#ifdef CONFIG_PCI
+       retval = pci_register_driver(&moxa_pci_driver);
+       if (retval) {
+               printk(KERN_ERR "Can't register MOXA pci driver!\n");
+               if (isabrds)
+                       retval = 0;
+       }
+#endif
+
+       return retval;
+}
+
+static void __exit moxa_exit(void)
+{
+       unsigned int i;
+
+#ifdef CONFIG_PCI
+       pci_unregister_driver(&moxa_pci_driver);
+#endif
+
+       for (i = 0; i < MAX_BOARDS; i++) /* ISA boards */
+               if (moxa_boards[i].ready)
+                       moxa_board_deinit(&moxa_boards[i]);
+
+       del_timer_sync(&moxaTimer);
+
+       if (tty_unregister_driver(moxaDriver))
+               printk(KERN_ERR "Couldn't unregister MOXA Intellio family "
+                               "serial driver\n");
+       put_tty_driver(moxaDriver);
 }
 
 module_init(moxa_init);
 module_exit(moxa_exit);
 
+static void moxa_close_port(struct moxa_port *ch)
+{
+       moxa_shut_down(ch);
+       MoxaPortFlushData(ch, 2);
+       ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
+       ch->tty->driver_data = NULL;
+       ch->tty = NULL;
+}
+
+static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp,
+                           struct moxa_port *ch)
+{
+       DEFINE_WAIT(wait);
+       int retval = 0;
+       u8 dcd;
+
+       while (1) {
+               prepare_to_wait(&ch->open_wait, &wait, TASK_INTERRUPTIBLE);
+               if (tty_hung_up_p(filp)) {
+#ifdef SERIAL_DO_RESTART
+                       retval = -ERESTARTSYS;
+#else
+                       retval = -EAGAIN;
+#endif
+                       break;
+               }
+               spin_lock_bh(&moxa_lock);
+               dcd = ch->DCDState;
+               spin_unlock_bh(&moxa_lock);
+               if (dcd)
+                       break;
+
+               if (signal_pending(current)) {
+                       retval = -ERESTARTSYS;
+                       break;
+               }
+               schedule();
+       }
+       finish_wait(&ch->open_wait, &wait);
+
+       return retval;
+}
+
 static int moxa_open(struct tty_struct *tty, struct file *filp)
 {
+       struct moxa_board_conf *brd;
        struct moxa_port *ch;
        int port;
        int retval;
 
        port = tty->index;
        if (port == MAX_PORTS) {
-               return (0);
+               return capable(CAP_SYS_ADMIN) ? 0 : -EPERM;
        }
-       if (!MoxaPortIsValid(port)) {
-               tty->driver_data = NULL;
-               return (-ENODEV);
+       if (mutex_lock_interruptible(&moxa_openlock))
+               return -ERESTARTSYS;
+       brd = &moxa_boards[port / MAX_PORTS_PER_BOARD];
+       if (!brd->ready) {
+               mutex_unlock(&moxa_openlock);
+               return -ENODEV;
        }
 
-       ch = &moxa_ports[port];
+       ch = &brd->ports[port % MAX_PORTS_PER_BOARD];
        ch->count++;
        tty->driver_data = ch;
        ch->tty = tty;
        if (!(ch->asyncflags & ASYNC_INITIALIZED)) {
                ch->statusflags = 0;
                moxa_set_tty_param(tty, tty->termios);
-               MoxaPortLineCtrl(ch->port, 1, 1);
-               MoxaPortEnable(ch->port);
+               MoxaPortLineCtrl(ch, 1, 1);
+               MoxaPortEnable(ch);
+               MoxaSetFifo(ch, ch->type == PORT_16550A);
                ch->asyncflags |= ASYNC_INITIALIZED;
        }
-       retval = moxa_block_till_ready(tty, filp, ch);
+       mutex_unlock(&moxa_openlock);
 
-       moxa_unthrottle(tty);
-
-       if (ch->type == PORT_16550A) {
-               MoxaSetFifo(ch->port, 1);
-       } else {
-               MoxaSetFifo(ch->port, 0);
-       }
+       retval = 0;
+       if (!(filp->f_flags & O_NONBLOCK) && !C_CLOCAL(tty))
+               retval = moxa_block_till_ready(tty, filp, ch);
+       mutex_lock(&moxa_openlock);
+       if (retval) {
+               if (ch->count) /* 0 means already hung up... */
+                       if (--ch->count == 0)
+                               moxa_close_port(ch);
+       } else
+               ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
+       mutex_unlock(&moxa_openlock);
 
-       return (retval);
+       return retval;
 }
 
 static void moxa_close(struct tty_struct *tty, struct file *filp)
@@ -524,23 +1197,14 @@ static void moxa_close(struct tty_struct *tty, struct file *filp)
        int port;
 
        port = tty->index;
-       if (port == MAX_PORTS) {
-               return;
-       }
-       if (!MoxaPortIsValid(port)) {
-               pr_debug("Invalid portno in moxa_close\n");
-               tty->driver_data = NULL;
+       if (port == MAX_PORTS || tty_hung_up_p(filp))
                return;
-       }
-       if (tty->driver_data == NULL) {
-               return;
-       }
-       if (tty_hung_up_p(filp)) {
-               return;
-       }
-       ch = (struct moxa_port *) tty->driver_data;
 
-       if ((tty->count == 1) && (ch->count != 1)) {
+       mutex_lock(&moxa_openlock);
+       ch = tty->driver_data;
+       if (ch == NULL)
+               goto unlock;
+       if (tty->count == 1 && ch->count != 1) {
                printk(KERN_WARNING "moxa_close: bad serial port count; "
                        "tty->count is 1, ch->count is %d\n", ch->count);
                ch->count = 1;
@@ -550,59 +1214,35 @@ static void moxa_close(struct tty_struct *tty, struct file *filp)
                        "device=%s\n", tty->name);
                ch->count = 0;
        }
-       if (ch->count) {
-               return;
-       }
-       ch->asyncflags |= ASYNC_CLOSING;
+       if (ch->count)
+               goto unlock;
 
        ch->cflag = tty->termios->c_cflag;
        if (ch->asyncflags & ASYNC_INITIALIZED) {
                moxa_setup_empty_event(tty);
                tty_wait_until_sent(tty, 30 * HZ);      /* 30 seconds timeout */
-               del_timer_sync(&moxa_ports[ch->port].emptyTimer);
        }
-       moxa_shut_down(ch);
-       MoxaPortFlushData(port, 2);
-
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
-       tty_ldisc_flush(tty);
-                       
-       tty->closing = 0;
-       ch->event = 0;
-       ch->tty = NULL;
-       if (ch->blocked_open) {
-               if (ch->close_delay) {
-                       msleep_interruptible(jiffies_to_msecs(ch->close_delay));
-               }
-               wake_up_interruptible(&ch->open_wait);
-       }
-       ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
-       complete_all(&ch->close_wait);
+
+       moxa_close_port(ch);
+unlock:
+       mutex_unlock(&moxa_openlock);
 }
 
 static int moxa_write(struct tty_struct *tty,
                      const unsigned char *buf, int count)
 {
-       struct moxa_port *ch;
-       int len, port;
-       unsigned long flags;
+       struct moxa_port *ch = tty->driver_data;
+       int len;
 
-       ch = (struct moxa_port *) tty->driver_data;
        if (ch == NULL)
-               return (0);
-       port = ch->port;
+               return 0;
 
-       spin_lock_irqsave(&moxa_lock, flags);
-       len = MoxaPortWriteData(port, (unsigned char *) buf, count);
-       spin_unlock_irqrestore(&moxa_lock, flags);
+       spin_lock_bh(&moxa_lock);
+       len = MoxaPortWriteData(ch, buf, count);
+       spin_unlock_bh(&moxa_lock);
 
-       /*********************************************
-       if ( !(ch->statusflags & LOWWAIT) &&
-            ((len != count) || (MoxaPortTxFree(port) <= 100)) )
-       ************************************************/
        ch->statusflags |= LOWWAIT;
-       return (len);
+       return len;
 }
 
 static int moxa_write_room(struct tty_struct *tty)
@@ -610,27 +1250,27 @@ static int moxa_write_room(struct tty_struct *tty)
        struct moxa_port *ch;
 
        if (tty->stopped)
-               return (0);
-       ch = (struct moxa_port *) tty->driver_data;
+               return 0;
+       ch = tty->driver_data;
        if (ch == NULL)
-               return (0);
-       return (MoxaPortTxFree(ch->port));
+               return 0;
+       return MoxaPortTxFree(ch);
 }
 
 static void moxa_flush_buffer(struct tty_struct *tty)
 {
-       struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
+       struct moxa_port *ch = tty->driver_data;
 
        if (ch == NULL)
                return;
-       MoxaPortFlushData(ch->port, 1);
+       MoxaPortFlushData(ch, 1);
        tty_wakeup(tty);
 }
 
 static int moxa_chars_in_buffer(struct tty_struct *tty)
 {
+       struct moxa_port *ch = tty->driver_data;
        int chars;
-       struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
 
        /*
         * Sigh...I have to check if driver_data is NULL here, because
@@ -639,8 +1279,9 @@ static int moxa_chars_in_buffer(struct tty_struct *tty)
         * routine.  And since the open() failed, we return 0 here.  TDJ
         */
        if (ch == NULL)
-               return (0);
-       chars = MoxaPortTxQueue(ch->port);
+               return 0;
+       lock_kernel();
+       chars = MoxaPortTxQueue(ch);
        if (chars) {
                /*
                 * Make it possible to wakeup anything waiting for output
@@ -649,73 +1290,54 @@ static int moxa_chars_in_buffer(struct tty_struct *tty)
                if (!(ch->statusflags & EMPTYWAIT))
                        moxa_setup_empty_event(tty);
        }
-       return (chars);
-}
-
-static void moxa_flush_chars(struct tty_struct *tty)
-{
-       /*
-        * Don't think I need this, because this is called to empty the TX
-        * buffer for the 16450, 16550, etc.
-        */
-}
-
-static void moxa_put_char(struct tty_struct *tty, unsigned char c)
-{
-       struct moxa_port *ch;
-       int port;
-       unsigned long flags;
-
-       ch = (struct moxa_port *) tty->driver_data;
-       if (ch == NULL)
-               return;
-       port = ch->port;
-       spin_lock_irqsave(&moxa_lock, flags);
-       MoxaPortWriteData(port, &c, 1);
-       spin_unlock_irqrestore(&moxa_lock, flags);
-       /************************************************
-       if ( !(ch->statusflags & LOWWAIT) && (MoxaPortTxFree(port) <= 100) )
-       *************************************************/
-       ch->statusflags |= LOWWAIT;
+       unlock_kernel();
+       return chars;
 }
 
 static int moxa_tiocmget(struct tty_struct *tty, struct file *file)
 {
-       struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
-       int port;
+       struct moxa_port *ch;
        int flag = 0, dtr, rts;
 
-       port = tty->index;
-       if ((port != MAX_PORTS) && (!ch))
-               return (-EINVAL);
+       mutex_lock(&moxa_openlock);
+       ch = tty->driver_data;
+       if (!ch) {
+               mutex_unlock(&moxa_openlock);
+               return -EINVAL;
+       }
 
-       MoxaPortGetLineOut(ch->port, &dtr, &rts);
+       MoxaPortGetLineOut(ch, &dtr, &rts);
        if (dtr)
                flag |= TIOCM_DTR;
        if (rts)
                flag |= TIOCM_RTS;
-       dtr = MoxaPortLineStatus(ch->port);
+       dtr = MoxaPortLineStatus(ch);
        if (dtr & 1)
                flag |= TIOCM_CTS;
        if (dtr & 2)
                flag |= TIOCM_DSR;
        if (dtr & 4)
                flag |= TIOCM_CD;
+       mutex_unlock(&moxa_openlock);
        return flag;
 }
 
 static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
                         unsigned int set, unsigned int clear)
 {
-       struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
+       struct moxa_port *ch;
        int port;
        int dtr, rts;
 
        port = tty->index;
-       if ((port != MAX_PORTS) && (!ch))
-               return (-EINVAL);
+       mutex_lock(&moxa_openlock);
+       ch = tty->driver_data;
+       if (!ch) {
+               mutex_unlock(&moxa_openlock);
+               return -EINVAL;
+       }
 
-       MoxaPortGetLineOut(ch->port, &dtr, &rts);
+       MoxaPortGetLineOut(ch, &dtr, &rts);
        if (set & TIOCM_RTS)
                rts = 1;
        if (set & TIOCM_DTR)
@@ -724,105 +1346,51 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
                rts = 0;
        if (clear & TIOCM_DTR)
                dtr = 0;
-       MoxaPortLineCtrl(ch->port, dtr, rts);
+       MoxaPortLineCtrl(ch, dtr, rts);
+       mutex_unlock(&moxa_openlock);
        return 0;
 }
 
-static int moxa_ioctl(struct tty_struct *tty, struct file *file,
-                     unsigned int cmd, unsigned long arg)
-{
-       struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
-       register int port;
-       void __user *argp = (void __user *)arg;
-       int retval;
-
-       port = tty->index;
-       if ((port != MAX_PORTS) && (!ch))
-               return (-EINVAL);
-
-       switch (cmd) {
-       case TCSBRK:            /* SVID version: non-zero arg --> no break */
-               retval = tty_check_change(tty);
-               if (retval)
-                       return (retval);
-               moxa_setup_empty_event(tty);
-               tty_wait_until_sent(tty, 0);
-               if (!arg)
-                       MoxaPortSendBreak(ch->port, 0);
-               return (0);
-       case TCSBRKP:           /* support for POSIX tcsendbreak() */
-               retval = tty_check_change(tty);
-               if (retval)
-                       return (retval);
-               moxa_setup_empty_event(tty);
-               tty_wait_until_sent(tty, 0);
-               MoxaPortSendBreak(ch->port, arg);
-               return (0);
-       case TIOCGSOFTCAR:
-               return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) argp);
-       case TIOCSSOFTCAR:
-               if(get_user(retval, (unsigned long __user *) argp))
-                       return -EFAULT;
-               arg = retval;
-               tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) |
-                                        (arg ? CLOCAL : 0));
-               if (C_CLOCAL(tty))
-                       ch->asyncflags &= ~ASYNC_CHECK_CD;
-               else
-                       ch->asyncflags |= ASYNC_CHECK_CD;
-               return (0);
-       case TIOCGSERIAL:
-               return moxa_get_serial_info(ch, argp);
-
-       case TIOCSSERIAL:
-               return moxa_set_serial_info(ch, argp);
-       default:
-               retval = MoxaDriverIoctl(cmd, arg, port);
-       }
-       return (retval);
-}
-
 static void moxa_throttle(struct tty_struct *tty)
 {
-       struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
+       struct moxa_port *ch = tty->driver_data;
 
        ch->statusflags |= THROTTLE;
 }
 
 static void moxa_unthrottle(struct tty_struct *tty)
 {
-       struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
+       struct moxa_port *ch = tty->driver_data;
 
        ch->statusflags &= ~THROTTLE;
 }
 
 static void moxa_set_termios(struct tty_struct *tty,
-                            struct ktermios *old_termios)
+               struct ktermios *old_termios)
 {
-       struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
+       struct moxa_port *ch = tty->driver_data;
 
        if (ch == NULL)
                return;
        moxa_set_tty_param(tty, old_termios);
-       if (!(old_termios->c_cflag & CLOCAL) &&
-           (tty->termios->c_cflag & CLOCAL))
+       if (!(old_termios->c_cflag & CLOCAL) && C_CLOCAL(tty))
                wake_up_interruptible(&ch->open_wait);
 }
 
 static void moxa_stop(struct tty_struct *tty)
 {
-       struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
+       struct moxa_port *ch = tty->driver_data;
 
        if (ch == NULL)
                return;
-       MoxaPortTxDisable(ch->port);
+       MoxaPortTxDisable(ch);
        ch->statusflags |= TXSTOPPED;
 }
 
 
 static void moxa_start(struct tty_struct *tty)
 {
-       struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
+       struct moxa_port *ch = tty->driver_data;
 
        if (ch == NULL)
                return;
@@ -830,91 +1398,143 @@ static void moxa_start(struct tty_struct *tty)
        if (!(ch->statusflags & TXSTOPPED))
                return;
 
-       MoxaPortTxEnable(ch->port);
+       MoxaPortTxEnable(ch);
        ch->statusflags &= ~TXSTOPPED;
 }
 
 static void moxa_hangup(struct tty_struct *tty)
 {
-       struct moxa_port *ch = (struct moxa_port *) tty->driver_data;
+       struct moxa_port *ch;
 
-       moxa_flush_buffer(tty);
-       moxa_shut_down(ch);
-       ch->event = 0;
+       mutex_lock(&moxa_openlock);
+       ch = tty->driver_data;
+       if (ch == NULL) {
+               mutex_unlock(&moxa_openlock);
+               return;
+       }
        ch->count = 0;
-       ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
-       ch->tty = NULL;
+       moxa_close_port(ch);
+       mutex_unlock(&moxa_openlock);
+
        wake_up_interruptible(&ch->open_wait);
 }
 
+static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
+{
+       dcd = !!dcd;
+
+       if (dcd != p->DCDState && p->tty && C_CLOCAL(p->tty)) {
+               if (!dcd)
+                       tty_hangup(p->tty);
+       }
+       p->DCDState = dcd;
+}
+
+static int moxa_poll_port(struct moxa_port *p, unsigned int handle,
+               u16 __iomem *ip)
+{
+       struct tty_struct *tty = p->tty;
+       void __iomem *ofsAddr;
+       unsigned int inited = p->asyncflags & ASYNC_INITIALIZED;
+       u16 intr;
+
+       if (tty) {
+               if ((p->statusflags & EMPTYWAIT) &&
+                               MoxaPortTxQueue(p) == 0) {
+                       p->statusflags &= ~EMPTYWAIT;
+                       tty_wakeup(tty);
+               }
+               if ((p->statusflags & LOWWAIT) && !tty->stopped &&
+                               MoxaPortTxQueue(p) <= WAKEUP_CHARS) {
+                       p->statusflags &= ~LOWWAIT;
+                       tty_wakeup(tty);
+               }
+
+               if (inited && !(p->statusflags & THROTTLE) &&
+                               MoxaPortRxQueue(p) > 0) { /* RX */
+                       MoxaPortReadData(p);
+                       tty_schedule_flip(tty);
+               }
+       } else {
+               p->statusflags &= ~EMPTYWAIT;
+               MoxaPortFlushData(p, 0); /* flush RX */
+       }
+
+       if (!handle) /* nothing else to do */
+               return 0;
+
+       intr = readw(ip); /* port irq status */
+       if (intr == 0)
+               return 0;
+
+       writew(0, ip); /* ACK port */
+       ofsAddr = p->tableAddr;
+       if (intr & IntrTx) /* disable tx intr */
+               writew(readw(ofsAddr + HostStat) & ~WakeupTx,
+                               ofsAddr + HostStat);
+
+       if (!inited)
+               return 0;
+
+       if (tty && (intr & IntrBreak) && !I_IGNBRK(tty)) { /* BREAK */
+               tty_insert_flip_char(tty, 0, TTY_BREAK);
+               tty_schedule_flip(tty);
+       }
+
+       if (intr & IntrLine)
+               moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state);
+
+       return 0;
+}
+
 static void moxa_poll(unsigned long ignored)
 {
-       register int card;
-       struct moxa_port *ch;
-       struct tty_struct *tp;
-       int i, ports;
-
-       del_timer(&moxaTimer);
+       struct moxa_board_conf *brd;
+       u16 __iomem *ip;
+       unsigned int card, port, served = 0;
 
-       if (MoxaDriverPoll() < 0) {
-               mod_timer(&moxaTimer, jiffies + HZ / 50);
-               return;
-       }
+       spin_lock(&moxa_lock);
        for (card = 0; card < MAX_BOARDS; card++) {
-               if ((ports = MoxaPortsOfCard(card)) <= 0)
+               brd = &moxa_boards[card];
+               if (!brd->ready)
                        continue;
-               ch = &moxa_ports[card * MAX_PORTS_PER_BOARD];
-               for (i = 0; i < ports; i++, ch++) {
-                       if ((ch->asyncflags & ASYNC_INITIALIZED) == 0)
-                               continue;
-                       if (!(ch->statusflags & THROTTLE) &&
-                           (MoxaPortRxQueue(ch->port) > 0))
-                               moxa_receive_data(ch);
-                       if ((tp = ch->tty) == 0)
-                               continue;
-                       if (ch->statusflags & LOWWAIT) {
-                               if (MoxaPortTxQueue(ch->port) <= WAKEUP_CHARS) {
-                                       if (!tp->stopped) {
-                                               ch->statusflags &= ~LOWWAIT;
-                                               tty_wakeup(tp);
-                                       }
-                               }
-                       }
-                       if (!I_IGNBRK(tp) && (MoxaPortResetBrkCnt(ch->port) > 0)) {
-                               tty_insert_flip_char(tp, 0, TTY_BREAK);
-                               tty_schedule_flip(tp);
-                       }
-                       if (MoxaPortDCDChange(ch->port)) {
-                               if (ch->asyncflags & ASYNC_CHECK_CD) {
-                                       if (MoxaPortDCDON(ch->port))
-                                               wake_up_interruptible(&ch->open_wait);
-                                       else {
-                                               tty_hangup(tp);
-                                               wake_up_interruptible(&ch->open_wait);
-                                               ch->asyncflags &= ~ASYNC_NORMAL_ACTIVE;
-                                       }
+
+               served++;
+
+               ip = NULL;
+               if (readb(brd->intPend) == 0xff)
+                       ip = brd->intTable + readb(brd->intNdx);
+
+               for (port = 0; port < brd->numPorts; port++)
+                       moxa_poll_port(&brd->ports[port], !!ip, ip + port);
+
+               if (ip)
+                       writeb(0, brd->intPend); /* ACK */
+
+               if (moxaLowWaterChk) {
+                       struct moxa_port *p = brd->ports;
+                       for (port = 0; port < brd->numPorts; port++, p++)
+                               if (p->lowChkFlag) {
+                                       p->lowChkFlag = 0;
+                                       moxa_low_water_check(p->tableAddr);
                                }
-                       }
                }
        }
+       moxaLowWaterChk = 0;
 
-       mod_timer(&moxaTimer, jiffies + HZ / 50);
+       if (served)
+               mod_timer(&moxaTimer, jiffies + HZ / 50);
+       spin_unlock(&moxa_lock);
 }
 
 /******************************************************************************/
 
 static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_termios)
 {
-       register struct ktermios *ts;
-       struct moxa_port *ch;
+       register struct ktermios *ts = tty->termios;
+       struct moxa_port *ch = tty->driver_data;
        int rts, cts, txflow, rxflow, xany, baud;
 
-       ch = (struct moxa_port *) tty->driver_data;
-       ts = tty->termios;
-       if (ts->c_cflag & CLOCAL)
-               ch->asyncflags &= ~ASYNC_CHECK_CD;
-       else
-               ch->asyncflags |= ASYNC_CHECK_CD;
        rts = cts = txflow = rxflow = xany = 0;
        if (ts->c_cflag & CRTSCTS)
                rts = cts = 1;
@@ -927,776 +1547,60 @@ static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_term
 
        /* Clear the features we don't support */
        ts->c_cflag &= ~CMSPAR;
-       MoxaPortFlowCtrl(ch->port, rts, cts, txflow, rxflow, xany);
-       baud = MoxaPortSetTermio(ch->port, ts, tty_get_baud_rate(tty));
+       MoxaPortFlowCtrl(ch, rts, cts, txflow, rxflow, xany);
+       baud = MoxaPortSetTermio(ch, ts, tty_get_baud_rate(tty));
        if (baud == -1)
                baud = tty_termios_baud_rate(old_termios);
        /* Not put the baud rate into the termios data */
        tty_encode_baud_rate(tty, baud, baud);
 }
 
-static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp,
-                           struct moxa_port *ch)
-{
-       DECLARE_WAITQUEUE(wait,current);
-       unsigned long flags;
-       int retval;
-       int do_clocal = C_CLOCAL(tty);
-
-       /*
-        * If the device is in the middle of being closed, then block
-        * until it's done, and then try again.
-        */
-       if (tty_hung_up_p(filp) || (ch->asyncflags & ASYNC_CLOSING)) {
-               if (ch->asyncflags & ASYNC_CLOSING)
-                       wait_for_completion_interruptible(&ch->close_wait);
-#ifdef SERIAL_DO_RESTART
-               if (ch->asyncflags & ASYNC_HUP_NOTIFY)
-                       return (-EAGAIN);
-               else
-                       return (-ERESTARTSYS);
-#else
-               return (-EAGAIN);
-#endif
-       }
-       /*
-        * If non-blocking mode is set, then make the check up front
-        * and then exit.
-        */
-       if (filp->f_flags & O_NONBLOCK) {
-               ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
-               return (0);
-       }
-       /*
-        * Block waiting for the carrier detect and the line to become free
-        */
-       retval = 0;
-       add_wait_queue(&ch->open_wait, &wait);
-       pr_debug("block_til_ready before block: ttys%d, count = %d\n",
-               ch->port, ch->count);
-       spin_lock_irqsave(&moxa_lock, flags);
-       if (!tty_hung_up_p(filp))
-               ch->count--;
-       ch->blocked_open++;
-       spin_unlock_irqrestore(&moxa_lock, flags);
-
-       while (1) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (tty_hung_up_p(filp) ||
-                   !(ch->asyncflags & ASYNC_INITIALIZED)) {
-#ifdef SERIAL_DO_RESTART
-                       if (ch->asyncflags & ASYNC_HUP_NOTIFY)
-                               retval = -EAGAIN;
-                       else
-                               retval = -ERESTARTSYS;
-#else
-                       retval = -EAGAIN;
-#endif
-                       break;
-               }
-               if (!(ch->asyncflags & ASYNC_CLOSING) && (do_clocal ||
-                                               MoxaPortDCDON(ch->port)))
-                       break;
-
-               if (signal_pending(current)) {
-                       retval = -ERESTARTSYS;
-                       break;
-               }
-               schedule();
-       }
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&ch->open_wait, &wait);
-
-       spin_lock_irqsave(&moxa_lock, flags);
-       if (!tty_hung_up_p(filp))
-               ch->count++;
-       ch->blocked_open--;
-       spin_unlock_irqrestore(&moxa_lock, flags);
-       pr_debug("block_til_ready after blocking: ttys%d, count = %d\n",
-               ch->port, ch->count);
-       if (retval)
-               return (retval);
-       /* FIXME: review to see if we need to use set_bit on these */
-       ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
-       return 0;
-}
-
 static void moxa_setup_empty_event(struct tty_struct *tty)
 {
        struct moxa_port *ch = tty->driver_data;
-       unsigned long flags;
 
-       spin_lock_irqsave(&moxa_lock, flags);
+       spin_lock_bh(&moxa_lock);
        ch->statusflags |= EMPTYWAIT;
-       mod_timer(&moxa_ports[ch->port].emptyTimer, jiffies + HZ);
-       spin_unlock_irqrestore(&moxa_lock, flags);
-}
-
-static void moxa_check_xmit_empty(unsigned long data)
-{
-       struct moxa_port *ch;
-
-       ch = (struct moxa_port *) data;
-       if (ch->tty && (ch->statusflags & EMPTYWAIT)) {
-               if (MoxaPortTxQueue(ch->port) == 0) {
-                       ch->statusflags &= ~EMPTYWAIT;
-                       tty_wakeup(ch->tty);
-                       return;
-               }
-               mod_timer(&moxa_ports[ch->port].emptyTimer,
-                               round_jiffies(jiffies + HZ));
-       } else
-               ch->statusflags &= ~EMPTYWAIT;
+       spin_unlock_bh(&moxa_lock);
 }
 
 static void moxa_shut_down(struct moxa_port *ch)
 {
-       struct tty_struct *tp;
+       struct tty_struct *tp = ch->tty;
 
        if (!(ch->asyncflags & ASYNC_INITIALIZED))
                return;
 
-       tp = ch->tty;
-
-       MoxaPortDisable(ch->port);
+       MoxaPortDisable(ch);
 
        /*
         * If we're a modem control device and HUPCL is on, drop RTS & DTR.
         */
-       if (tp->termios->c_cflag & HUPCL)
-               MoxaPortLineCtrl(ch->port, 0, 0);
+       if (C_HUPCL(tp))
+               MoxaPortLineCtrl(ch, 0, 0);
 
+       spin_lock_bh(&moxa_lock);
        ch->asyncflags &= ~ASYNC_INITIALIZED;
+       spin_unlock_bh(&moxa_lock);
 }
 
-static void moxa_receive_data(struct moxa_port *ch)
-{
-       struct tty_struct *tp;
-       struct ktermios *ts;
-       unsigned long flags;
-
-       ts = NULL;
-       tp = ch->tty;
-       if (tp)
-               ts = tp->termios;
-       /**************************************************
-       if ( !tp || !ts || !(ts->c_cflag & CREAD) ) {
-       *****************************************************/
-       if (!tp || !ts) {
-               MoxaPortFlushData(ch->port, 0);
-               return;
-       }
-       spin_lock_irqsave(&moxa_lock, flags);
-       MoxaPortReadData(ch->port, tp);
-       spin_unlock_irqrestore(&moxa_lock, flags);
-       tty_schedule_flip(tp);
-}
-
-#define Magic_code     0x404
-
-/*
- *    System Configuration
- */
-/*
- *    for C218 BIOS initialization
- */
-#define C218_ConfBase  0x800
-#define C218_status    (C218_ConfBase + 0)     /* BIOS running status    */
-#define C218_diag      (C218_ConfBase + 2)     /* diagnostic status      */
-#define C218_key       (C218_ConfBase + 4)     /* WORD (0x218 for C218) */
-#define C218DLoad_len  (C218_ConfBase + 6)     /* WORD           */
-#define C218check_sum  (C218_ConfBase + 8)     /* BYTE           */
-#define C218chksum_ok  (C218_ConfBase + 0x0a)  /* BYTE (1:ok)            */
-#define C218_TestRx    (C218_ConfBase + 0x10)  /* 8 bytes for 8 ports    */
-#define C218_TestTx    (C218_ConfBase + 0x18)  /* 8 bytes for 8 ports    */
-#define C218_RXerr     (C218_ConfBase + 0x20)  /* 8 bytes for 8 ports    */
-#define C218_ErrFlag   (C218_ConfBase + 0x28)  /* 8 bytes for 8 ports    */
-
-#define C218_LoadBuf   0x0F00
-#define C218_KeyCode   0x218
-#define CP204J_KeyCode 0x204
-
-/*
- *    for C320 BIOS initialization
- */
-#define C320_ConfBase  0x800
-#define C320_LoadBuf   0x0f00
-#define STS_init       0x05    /* for C320_status        */
-
-#define C320_status    C320_ConfBase + 0       /* BIOS running status    */
-#define C320_diag      C320_ConfBase + 2       /* diagnostic status      */
-#define C320_key       C320_ConfBase + 4       /* WORD (0320H for C320) */
-#define C320DLoad_len  C320_ConfBase + 6       /* WORD           */
-#define C320check_sum  C320_ConfBase + 8       /* WORD           */
-#define C320chksum_ok  C320_ConfBase + 0x0a    /* WORD (1:ok)            */
-#define C320bapi_len   C320_ConfBase + 0x0c    /* WORD           */
-#define C320UART_no    C320_ConfBase + 0x0e    /* WORD           */
-
-#define C320_KeyCode   0x320
-
-#define FixPage_addr   0x0000  /* starting addr of static page  */
-#define DynPage_addr   0x2000  /* starting addr of dynamic page */
-#define C218_start     0x3000  /* starting addr of C218 BIOS prg */
-#define Control_reg    0x1ff0  /* select page and reset control */
-#define HW_reset       0x80
-
-/*
- *    Function Codes
- */
-#define FC_CardReset   0x80
-#define FC_ChannelReset 1      /* C320 firmware not supported */
-#define FC_EnableCH    2
-#define FC_DisableCH   3
-#define FC_SetParam    4
-#define FC_SetMode     5
-#define FC_SetRate     6
-#define FC_LineControl 7
-#define FC_LineStatus  8
-#define FC_XmitControl 9
-#define FC_FlushQueue  10
-#define FC_SendBreak   11
-#define FC_StopBreak   12
-#define FC_LoopbackON  13
-#define FC_LoopbackOFF 14
-#define FC_ClrIrqTable 15
-#define FC_SendXon     16
-#define FC_SetTermIrq  17      /* C320 firmware not supported */
-#define FC_SetCntIrq   18      /* C320 firmware not supported */
-#define FC_SetBreakIrq 19
-#define FC_SetLineIrq  20
-#define FC_SetFlowCtl  21
-#define FC_GenIrq      22
-#define FC_InCD180     23
-#define FC_OutCD180    24
-#define FC_InUARTreg   23
-#define FC_OutUARTreg  24
-#define FC_SetXonXoff  25
-#define FC_OutCD180CCR 26
-#define FC_ExtIQueue   27
-#define FC_ExtOQueue   28
-#define FC_ClrLineIrq  29
-#define FC_HWFlowCtl   30
-#define FC_GetClockRate 35
-#define FC_SetBaud     36
-#define FC_SetDataMode  41
-#define FC_GetCCSR      43
-#define FC_GetDataError 45
-#define FC_RxControl   50
-#define FC_ImmSend     51
-#define FC_SetXonState 52
-#define FC_SetXoffState        53
-#define FC_SetRxFIFOTrig 54
-#define FC_SetTxFIFOCnt 55
-#define FC_UnixRate    56
-#define FC_UnixResetTimer 57
-
-#define        RxFIFOTrig1     0
-#define        RxFIFOTrig4     1
-#define        RxFIFOTrig8     2
-#define        RxFIFOTrig14    3
-
-/*
- *    Dual-Ported RAM
- */
-#define DRAM_global    0
-#define INT_data       (DRAM_global + 0)
-#define Config_base    (DRAM_global + 0x108)
-
-#define IRQindex       (INT_data + 0)
-#define IRQpending     (INT_data + 4)
-#define IRQtable       (INT_data + 8)
-
-/*
- *    Interrupt Status
- */
-#define IntrRx         0x01    /* receiver data O.K.             */
-#define IntrTx         0x02    /* transmit buffer empty  */
-#define IntrFunc       0x04    /* function complete              */
-#define IntrBreak      0x08    /* received break         */
-#define IntrLine       0x10    /* line status change
-                                  for transmitter                */
-#define IntrIntr       0x20    /* received INTR code             */
-#define IntrQuit       0x40    /* received QUIT code             */
-#define IntrEOF        0x80    /* received EOF code              */
-
-#define IntrRxTrigger  0x100   /* rx data count reach tigger value */
-#define IntrTxTrigger  0x200   /* tx data count below trigger value */
-
-#define Magic_no       (Config_base + 0)
-#define Card_model_no  (Config_base + 2)
-#define Total_ports    (Config_base + 4)
-#define Module_cnt     (Config_base + 8)
-#define Module_no      (Config_base + 10)
-#define Timer_10ms     (Config_base + 14)
-#define Disable_IRQ    (Config_base + 20)
-#define TMS320_PORT1   (Config_base + 22)
-#define TMS320_PORT2   (Config_base + 24)
-#define TMS320_CLOCK   (Config_base + 26)
-
-/*
- *    DATA BUFFER in DRAM
- */
-#define Extern_table   0x400   /* Base address of the external table
-                                  (24 words *    64) total 3K bytes
-                                  (24 words * 128) total 6K bytes */
-#define Extern_size    0x60    /* 96 bytes                       */
-#define RXrptr         0x00    /* read pointer for RX buffer     */
-#define RXwptr         0x02    /* write pointer for RX buffer    */
-#define TXrptr         0x04    /* read pointer for TX buffer     */
-#define TXwptr         0x06    /* write pointer for TX buffer    */
-#define HostStat       0x08    /* IRQ flag and general flag      */
-#define FlagStat       0x0A
-#define FlowControl    0x0C    /* B7 B6 B5 B4 B3 B2 B1 B0              */
-                                       /*  x  x  x  x  |  |  |  |            */
-                                       /*              |  |  |  + CTS flow   */
-                                       /*              |  |  +--- RTS flow   */
-                                       /*              |  +------ TX Xon/Xoff */
-                                       /*              +--------- RX Xon/Xoff */
-#define Break_cnt      0x0E    /* received break count   */
-#define CD180TXirq     0x10    /* if non-0: enable TX irq        */
-#define RX_mask        0x12
-#define TX_mask        0x14
-#define Ofs_rxb        0x16
-#define Ofs_txb        0x18
-#define Page_rxb       0x1A
-#define Page_txb       0x1C
-#define EndPage_rxb    0x1E
-#define EndPage_txb    0x20
-#define Data_error     0x22
-#define RxTrigger      0x28
-#define TxTrigger      0x2a
-
-#define rRXwptr        0x34
-#define Low_water      0x36
-
-#define FuncCode       0x40
-#define FuncArg        0x42
-#define FuncArg1       0x44
-
-#define C218rx_size    0x2000  /* 8K bytes */
-#define C218tx_size    0x8000  /* 32K bytes */
-
-#define C218rx_mask    (C218rx_size - 1)
-#define C218tx_mask    (C218tx_size - 1)
-
-#define C320p8rx_size  0x2000
-#define C320p8tx_size  0x8000
-#define C320p8rx_mask  (C320p8rx_size - 1)
-#define C320p8tx_mask  (C320p8tx_size - 1)
-
-#define C320p16rx_size 0x2000
-#define C320p16tx_size 0x4000
-#define C320p16rx_mask (C320p16rx_size - 1)
-#define C320p16tx_mask (C320p16tx_size - 1)
-
-#define C320p24rx_size 0x2000
-#define C320p24tx_size 0x2000
-#define C320p24rx_mask (C320p24rx_size - 1)
-#define C320p24tx_mask (C320p24tx_size - 1)
-
-#define C320p32rx_size 0x1000
-#define C320p32tx_size 0x1000
-#define C320p32rx_mask (C320p32rx_size - 1)
-#define C320p32tx_mask (C320p32tx_size - 1)
-
-#define Page_size      0x2000
-#define Page_mask      (Page_size - 1)
-#define C218rx_spage   3
-#define C218tx_spage   4
-#define C218rx_pageno  1
-#define C218tx_pageno  4
-#define C218buf_pageno 5
-
-#define C320p8rx_spage 3
-#define C320p8tx_spage 4
-#define C320p8rx_pgno  1
-#define C320p8tx_pgno  4
-#define C320p8buf_pgno 5
-
-#define C320p16rx_spage 3
-#define C320p16tx_spage 4
-#define C320p16rx_pgno 1
-#define C320p16tx_pgno 2
-#define C320p16buf_pgno 3
-
-#define C320p24rx_spage 3
-#define C320p24tx_spage 4
-#define C320p24rx_pgno 1
-#define C320p24tx_pgno 1
-#define C320p24buf_pgno 2
-
-#define C320p32rx_spage 3
-#define C320p32tx_ofs  C320p32rx_size
-#define C320p32tx_spage 3
-#define C320p32buf_pgno 1
-
-/*
- *    Host Status
- */
-#define WakeupRx       0x01
-#define WakeupTx       0x02
-#define WakeupBreak    0x08
-#define WakeupLine     0x10
-#define WakeupIntr     0x20
-#define WakeupQuit     0x40
-#define WakeupEOF      0x80    /* used in VTIME control */
-#define WakeupRxTrigger        0x100
-#define WakeupTxTrigger        0x200
-/*
- *    Flag status
- */
-#define Rx_over                0x01
-#define Xoff_state     0x02
-#define Tx_flowOff     0x04
-#define Tx_enable      0x08
-#define CTS_state      0x10
-#define DSR_state      0x20
-#define DCD_state      0x80
-/*
- *    FlowControl
- */
-#define CTS_FlowCtl    1
-#define RTS_FlowCtl    2
-#define Tx_FlowCtl     4
-#define Rx_FlowCtl     8
-#define IXM_IXANY      0x10
-
-#define LowWater       128
-
-#define DTR_ON         1
-#define RTS_ON         2
-#define CTS_ON         1
-#define DSR_ON         2
-#define DCD_ON         8
-
-/* mode definition */
-#define        MX_CS8          0x03
-#define        MX_CS7          0x02
-#define        MX_CS6          0x01
-#define        MX_CS5          0x00
-
-#define        MX_STOP1        0x00
-#define        MX_STOP15       0x04
-#define        MX_STOP2        0x08
-
-#define        MX_PARNONE      0x00
-#define        MX_PAREVEN      0x40
-#define        MX_PARODD       0xC0
-
-/*
- *    Query
- */
-
-struct mon_str {
-       int tick;
-       int rxcnt[MAX_PORTS];
-       int txcnt[MAX_PORTS];
-};
-
-#define        DCD_changed     0x01
-#define        DCD_oldstate    0x80
-
-static unsigned char moxaBuff[10240];
-static int moxaLowWaterChk;
-static int moxaCard;
-static struct mon_str moxaLog;
-static int moxaFuncTout = HZ / 2;
-
-static void moxafunc(void __iomem *, int, ushort);
-static void moxa_wait_finish(void __iomem *);
-static void moxa_low_water_check(void __iomem *);
-static int moxaloadbios(int, unsigned char __user *, int);
-static int moxafindcard(int);
-static int moxaload320b(int, unsigned char __user *, int);
-static int moxaloadcode(int, unsigned char __user *, int);
-static int moxaloadc218(int, void __iomem *, int);
-static int moxaloadc320(int, void __iomem *, int, int *);
-
 /*****************************************************************************
  *     Driver level functions:                                              *
- *     1. MoxaDriverInit(void);                                             *
- *     2. MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port);   *
- *     3. MoxaDriverPoll(void);                                             *
  *****************************************************************************/
-void MoxaDriverInit(void)
-{
-       struct moxa_port *p;
-       unsigned int i;
-
-       moxaFuncTout = HZ / 2;  /* 500 mini-seconds */
-       moxaCard = 0;
-       moxaLog.tick = 0;
-       moxaLowWaterChk = 0;
-       for (i = 0; i < MAX_PORTS; i++) {
-               p = &moxa_ports[i];
-               p->chkPort = 0;
-               p->lowChkFlag = 0;
-               p->lineCtrl = 0;
-               moxaLog.rxcnt[i] = 0;
-               moxaLog.txcnt[i] = 0;
-       }
-}
-
-#define        MOXA            0x400
-#define MOXA_GET_IQUEUE        (MOXA + 1)      /* get input buffered count */
-#define MOXA_GET_OQUEUE        (MOXA + 2)      /* get output buffered count */
-#define MOXA_INIT_DRIVER       (MOXA + 6)      /* moxaCard=0 */
-#define MOXA_LOAD_BIOS         (MOXA + 9)      /* download BIOS */
-#define MOXA_FIND_BOARD                (MOXA + 10)     /* Check if MOXA card exist? */
-#define MOXA_LOAD_C320B                (MOXA + 11)     /* download 320B firmware */
-#define MOXA_LOAD_CODE         (MOXA + 12)     /* download firmware */
-#define MOXA_GETDATACOUNT       (MOXA + 23)
-#define MOXA_GET_IOQUEUE       (MOXA + 27)
-#define MOXA_FLUSH_QUEUE       (MOXA + 28)
-#define MOXA_GET_CONF          (MOXA + 35)     /* configuration */
-#define MOXA_GET_MAJOR          (MOXA + 63)
-#define MOXA_GET_CUMAJOR        (MOXA + 64)
-#define MOXA_GETMSTATUS         (MOXA + 65)
-
-struct dl_str {
-       char __user *buf;
-       int len;
-       int cardno;
-};
-
-static struct dl_str dltmp;
 
-void MoxaPortFlushData(int port, int mode)
+static void MoxaPortFlushData(struct moxa_port *port, int mode)
 {
        void __iomem *ofsAddr;
-       if ((mode < 0) || (mode > 2))
+       if (mode < 0 || mode > 2)
                return;
-       ofsAddr = moxa_ports[port].tableAddr;
+       ofsAddr = port->tableAddr;
        moxafunc(ofsAddr, FC_FlushQueue, mode);
        if (mode != 1) {
-               moxa_ports[port].lowChkFlag = 0;
+               port->lowChkFlag = 0;
                moxa_low_water_check(ofsAddr);
        }
 }
 
-int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port)
-{
-       int i;
-       int status;
-       int MoxaPortTxQueue(int), MoxaPortRxQueue(int);
-       void __user *argp = (void __user *)arg;
-
-       if (port == MAX_PORTS) {
-               if ((cmd != MOXA_GET_CONF) && (cmd != MOXA_INIT_DRIVER) &&
-                   (cmd != MOXA_LOAD_BIOS) && (cmd != MOXA_FIND_BOARD) && (cmd != MOXA_LOAD_C320B) &&
-                (cmd != MOXA_LOAD_CODE) && (cmd != MOXA_GETDATACOUNT) &&
-                 (cmd != MOXA_GET_IOQUEUE) && (cmd != MOXA_GET_MAJOR) &&
-                   (cmd != MOXA_GET_CUMAJOR) && (cmd != MOXA_GETMSTATUS))
-                       return (-EINVAL);
-       }
-       switch (cmd) {
-       case MOXA_GET_CONF:
-               if(copy_to_user(argp, &moxa_boards, MAX_BOARDS *
-                               sizeof(struct moxa_board_conf)))
-                       return -EFAULT;
-               return (0);
-       case MOXA_INIT_DRIVER:
-               if ((int) arg == 0x404)
-                       MoxaDriverInit();
-               return (0);
-       case MOXA_GETDATACOUNT:
-               moxaLog.tick = jiffies;
-               if(copy_to_user(argp, &moxaLog, sizeof(struct mon_str)))
-                       return -EFAULT;
-               return (0);
-       case MOXA_FLUSH_QUEUE:
-               MoxaPortFlushData(port, arg);
-               return (0);
-       case MOXA_GET_IOQUEUE: {
-               struct moxaq_str __user *argm = argp;
-               struct moxaq_str tmp;
-
-               for (i = 0; i < MAX_PORTS; i++, argm++) {
-                       memset(&tmp, 0, sizeof(tmp));
-                       if (moxa_ports[i].chkPort) {
-                               tmp.inq = MoxaPortRxQueue(i);
-                               tmp.outq = MoxaPortTxQueue(i);
-                       }
-                       if (copy_to_user(argm, &tmp, sizeof(tmp)))
-                               return -EFAULT;
-               }
-               return (0);
-       } case MOXA_GET_OQUEUE:
-               i = MoxaPortTxQueue(port);
-               return put_user(i, (unsigned long __user *)argp);
-       case MOXA_GET_IQUEUE:
-               i = MoxaPortRxQueue(port);
-               return put_user(i, (unsigned long __user *)argp);
-       case MOXA_GET_MAJOR:
-               if(copy_to_user(argp, &ttymajor, sizeof(int)))
-                       return -EFAULT;
-               return 0;
-       case MOXA_GET_CUMAJOR:
-               i = 0;
-               if(copy_to_user(argp, &i, sizeof(int)))
-                       return -EFAULT;
-               return 0;
-       case MOXA_GETMSTATUS: {
-               struct mxser_mstatus __user *argm = argp;
-               struct mxser_mstatus tmp;
-               struct moxa_port *p;
-
-               for (i = 0; i < MAX_PORTS; i++, argm++) {
-                       p = &moxa_ports[i];
-                       memset(&tmp, 0, sizeof(tmp));
-                       if (!p->chkPort) {
-                               goto copy;
-                       } else {
-                               status = MoxaPortLineStatus(p->port);
-                               if (status & 1)
-                                       tmp.cts = 1;
-                               if (status & 2)
-                                       tmp.dsr = 1;
-                               if (status & 4)
-                                       tmp.dcd = 1;
-                       }
-
-                       if (!p->tty || !p->tty->termios)
-                               tmp.cflag = p->cflag;
-                       else
-                               tmp.cflag = p->tty->termios->c_cflag;
-copy:
-                       if (copy_to_user(argm, &tmp, sizeof(tmp)))
-                               return -EFAULT;
-               }
-               return 0;
-       } default:
-               return (-ENOIOCTLCMD);
-       case MOXA_LOAD_BIOS:
-       case MOXA_FIND_BOARD:
-       case MOXA_LOAD_C320B:
-       case MOXA_LOAD_CODE:
-               if (!capable(CAP_SYS_RAWIO))
-                       return -EPERM;
-               break;
-       }
-
-       if(copy_from_user(&dltmp, argp, sizeof(struct dl_str)))
-               return -EFAULT;
-       if(dltmp.cardno < 0 || dltmp.cardno >= MAX_BOARDS || dltmp.len < 0)
-               return -EINVAL;
-
-       switch(cmd)
-       {
-       case MOXA_LOAD_BIOS:
-               i = moxaloadbios(dltmp.cardno, dltmp.buf, dltmp.len);
-               return (i);
-       case MOXA_FIND_BOARD:
-               return moxafindcard(dltmp.cardno);
-       case MOXA_LOAD_C320B:
-               moxaload320b(dltmp.cardno, dltmp.buf, dltmp.len);
-       default: /* to keep gcc happy */
-               return (0);
-       case MOXA_LOAD_CODE:
-               i = moxaloadcode(dltmp.cardno, dltmp.buf, dltmp.len);
-               if (i == -1)
-                       return (-EFAULT);
-               return (i);
-
-       }
-}
-
-int MoxaDriverPoll(void)
-{
-       struct moxa_board_conf *brd;
-       register ushort temp;
-       register int card;
-       void __iomem *ofsAddr;
-       void __iomem *ip;
-       int port, p, ports;
-
-       if (moxaCard == 0)
-               return (-1);
-       for (card = 0; card < MAX_BOARDS; card++) {
-               brd = &moxa_boards[card];
-               if (brd->loadstat == 0)
-                       continue;
-               if ((ports = brd->numPorts) == 0)
-                       continue;
-               if (readb(brd->intPend) == 0xff) {
-                       ip = brd->intTable + readb(brd->intNdx);
-                       p = card * MAX_PORTS_PER_BOARD;
-                       ports <<= 1;
-                       for (port = 0; port < ports; port += 2, p++) {
-                               if ((temp = readw(ip + port)) != 0) {
-                                       writew(0, ip + port);
-                                       ofsAddr = moxa_ports[p].tableAddr;
-                                       if (temp & IntrTx)
-                                               writew(readw(ofsAddr + HostStat) & ~WakeupTx, ofsAddr + HostStat);
-                                       if (temp & IntrBreak) {
-                                               moxa_ports[p].breakCnt++;
-                                       }
-                                       if (temp & IntrLine) {
-                                               if (readb(ofsAddr + FlagStat) & DCD_state) {
-                                                       if ((moxa_ports[p].DCDState & DCD_oldstate) == 0)
-                                                               moxa_ports[p].DCDState = (DCD_oldstate |
-                                                                                  DCD_changed);
-                                               } else {
-                                                       if (moxa_ports[p].DCDState & DCD_oldstate)
-                                                               moxa_ports[p].DCDState = DCD_changed;
-                                               }
-                                       }
-                               }
-                       }
-                       writeb(0, brd->intPend);
-               }
-               if (moxaLowWaterChk) {
-                       p = card * MAX_PORTS_PER_BOARD;
-                       for (port = 0; port < ports; port++, p++) {
-                               if (moxa_ports[p].lowChkFlag) {
-                                       moxa_ports[p].lowChkFlag = 0;
-                                       ofsAddr = moxa_ports[p].tableAddr;
-                                       moxa_low_water_check(ofsAddr);
-                               }
-                       }
-               }
-       }
-       moxaLowWaterChk = 0;
-       return (0);
-}
-
-/*****************************************************************************
- *     Card level function:                                                 *
- *     1. MoxaPortsOfCard(int cardno);                                      *
- *****************************************************************************/
-int MoxaPortsOfCard(int cardno)
-{
-
-       if (moxa_boards[cardno].boardType == 0)
-               return (0);
-       return (moxa_boards[cardno].numPorts);
-}
-
-/*****************************************************************************
- *     Port level functions:                                                *
- *     1.  MoxaPortIsValid(int port);                                       *
- *     2.  MoxaPortEnable(int port);                                        *
- *     3.  MoxaPortDisable(int port);                                       *
- *     4.  MoxaPortGetMaxBaud(int port);                                    *
- *     6.  MoxaPortSetBaud(int port, long baud);                            *
- *     8.  MoxaPortSetTermio(int port, unsigned char *termio);              *
- *     9.  MoxaPortGetLineOut(int port, int *dtrState, int *rtsState);      *
- *     10. MoxaPortLineCtrl(int port, int dtrState, int rtsState);          *
- *     11. MoxaPortFlowCtrl(int port, int rts, int cts, int rx, int tx,int xany);    *
- *     12. MoxaPortLineStatus(int port);                                    *
- *     13. MoxaPortDCDChange(int port);                                     *
- *     14. MoxaPortDCDON(int port);                                         *
- *     15. MoxaPortFlushData(int port, int mode);                           *
- *     16. MoxaPortWriteData(int port, unsigned char * buffer, int length); *
- *     17. MoxaPortReadData(int port, struct tty_struct *tty);              *
- *     20. MoxaPortTxQueue(int port);                                       *
- *     21. MoxaPortTxFree(int port);                                        *
- *     22. MoxaPortRxQueue(int port);                                       *
- *     24. MoxaPortTxDisable(int port);                                     *
- *     25. MoxaPortTxEnable(int port);                                      *
- *     27. MoxaPortResetBrkCnt(int port);                                   *
- *     30. MoxaPortSendBreak(int port, int ticks);                          *
- *****************************************************************************/
 /*
  *    Moxa Port Number Description:
  *
@@ -1733,33 +1637,6 @@ int MoxaPortsOfCard(int cardno)
  *                      -ENOIOCTLCMD
  *
  *
- *      Function 3:     Moxa driver polling process routine.
- *      Syntax:
- *      int  MoxaDriverPoll(void);
- *
- *           return:    0       ; polling O.K.
- *                      -1      : no any Moxa card.             
- *
- *
- *      Function 4:     Get the ports of this card.
- *      Syntax:
- *      int  MoxaPortsOfCard(int cardno);
- *
- *           int cardno         : card number (0 - 3)
- *
- *           return:    0       : this card is invalid
- *                      8/16/24/32
- *
- *
- *      Function 5:     Check this port is valid or invalid
- *      Syntax:
- *      int  MoxaPortIsValid(int port);
- *           int port           : port number (0 - 127, ref port description)
- *
- *           return:    0       : this port is invalid
- *                      1       : this port is valid
- *
- *
  *      Function 6:     Enable this port to start Tx/Rx data.
  *      Syntax:
  *      void MoxaPortEnable(int port);
@@ -1772,18 +1649,9 @@ int MoxaPortsOfCard(int cardno)
  *           int port           : port number (0 - 127)
  *
  *
- *      Function 8:     Get the maximun available baud rate of this port.
- *      Syntax:
- *      long MoxaPortGetMaxBaud(int port);
- *           int port           : port number (0 - 127)
- *
- *           return:    0       : this port is invalid
- *                      38400/57600/115200 bps
- *
- *
  *      Function 10:    Setting baud rate of this port.
  *      Syntax:
- *      long MoxaPortSetBaud(int port, long baud);
+ *      speed_t MoxaPortSetBaud(int port, speed_t baud);
  *           int port           : port number (0 - 127)
  *           long baud          : baud rate (50 - 115200)
  *
@@ -1850,25 +1718,6 @@ int MoxaPortsOfCard(int cardno)
  *                      Bit 2 - DCD state (0: off, 1: on)
  *
  *
- *      Function 17:    Check the DCD state has changed since the last read
- *                      of this function.
- *      Syntax:
- *      int  MoxaPortDCDChange(int port);
- *           int port           : port number (0 - 127)
- *
- *           return:    0       : no changed
- *                      1       : DCD has changed
- *
- *
- *      Function 18:    Check ths current DCD state is ON or not.
- *      Syntax:
- *      int  MoxaPortDCDON(int port);
- *           int port           : port number (0 - 127)
- *
- *           return:    0       : DCD off
- *                      1       : DCD on
- *
- *
  *      Function 19:    Flush the Rx/Tx buffer data of this port.
  *      Syntax:
  *      void MoxaPortFlushData(int port, int mode);
@@ -1942,40 +1791,20 @@ int MoxaPortsOfCard(int cardno)
  *           return:    0 - ..  : BREAK signal count
  *
  *
- *      Function 34:    Send out a BREAK signal.
- *      Syntax:
- *      void MoxaPortSendBreak(int port, int ms100);
- *           int port           : port number (0 - 127)
- *           int ms100          : break signal time interval.
- *                                unit: 100 mini-second. if ms100 == 0, it will
- *                                send out a about 250 ms BREAK signal.
- *
  */
-int MoxaPortIsValid(int port)
-{
-
-       if (moxaCard == 0)
-               return (0);
-       if (moxa_ports[port].chkPort == 0)
-               return (0);
-       return (1);
-}
 
-void MoxaPortEnable(int port)
+static void MoxaPortEnable(struct moxa_port *port)
 {
        void __iomem *ofsAddr;
-       int MoxaPortLineStatus(int);
-       short lowwater = 512;
+       u16 lowwater = 512;
 
-       ofsAddr = moxa_ports[port].tableAddr;
+       ofsAddr = port->tableAddr;
        writew(lowwater, ofsAddr + Low_water);
-       moxa_ports[port].breakCnt = 0;
-       if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
-           (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
+       if (MOXA_IS_320(port->board))
                moxafunc(ofsAddr, FC_SetBreakIrq, 0);
-       } else {
-               writew(readw(ofsAddr + HostStat) | WakeupBreak, ofsAddr + HostStat);
-       }
+       else
+               writew(readw(ofsAddr + HostStat) | WakeupBreak,
+                               ofsAddr + HostStat);
 
        moxafunc(ofsAddr, FC_SetLineIrq, Magic_code);
        moxafunc(ofsAddr, FC_FlushQueue, 2);
@@ -1984,9 +1813,9 @@ void MoxaPortEnable(int port)
        MoxaPortLineStatus(port);
 }
 
-void MoxaPortDisable(int port)
+static void MoxaPortDisable(struct moxa_port *port)
 {
-       void __iomem *ofsAddr = moxa_ports[port].tableAddr;
+       void __iomem *ofsAddr = port->tableAddr;
 
        moxafunc(ofsAddr, FC_SetFlowCtl, 0);    /* disable flow control */
        moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code);
@@ -1994,49 +1823,32 @@ void MoxaPortDisable(int port)
        moxafunc(ofsAddr, FC_DisableCH, Magic_code);
 }
 
-long MoxaPortGetMaxBaud(int port)
-{
-       if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
-           (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI))
-               return (460800L);
-       else
-               return (921600L);
-}
-
-
-long MoxaPortSetBaud(int port, long baud)
+static speed_t MoxaPortSetBaud(struct moxa_port *port, speed_t baud)
 {
-       void __iomem *ofsAddr;
-       long max, clock;
-       unsigned int val;
+       void __iomem *ofsAddr = port->tableAddr;
+       unsigned int clock, val;
+       speed_t max;
 
-       if ((baud < 50L) || ((max = MoxaPortGetMaxBaud(port)) == 0))
-               return (0);
-       ofsAddr = moxa_ports[port].tableAddr;
+       max = MOXA_IS_320(port->board) ? 460800 : 921600;
+       if (baud < 50)
+               return 0;
        if (baud > max)
                baud = max;
-       if (max == 38400L)
-               clock = 614400L;        /* for 9.8304 Mhz : max. 38400 bps */
-       else if (max == 57600L)
-               clock = 691200L;        /* for 11.0592 Mhz : max. 57600 bps */
-       else
-               clock = 921600L;        /* for 14.7456 Mhz : max. 115200 bps */
+       clock = 921600;
        val = clock / baud;
        moxafunc(ofsAddr, FC_SetBaud, val);
        baud = clock / val;
-       moxa_ports[port].curBaud = baud;
-       return (baud);
+       return baud;
 }
 
-int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud)
+static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio,
+               speed_t baud)
 {
        void __iomem *ofsAddr;
        tcflag_t cflag;
        tcflag_t mode = 0;
 
-       if (moxa_ports[port].chkPort == 0 || termio == 0)
-               return (-1);
-       ofsAddr = moxa_ports[port].tableAddr;
+       ofsAddr = port->tableAddr;
        cflag = termio->c_cflag;        /* termio->c_cflag */
 
        mode = termio->c_cflag & CSIZE;
@@ -2065,13 +1877,11 @@ int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud)
        } else
                mode |= MX_PARNONE;
 
-       moxafunc(ofsAddr, FC_SetDataMode, (ushort) mode);
+       moxafunc(ofsAddr, FC_SetDataMode, (u16)mode);
+
+       if (MOXA_IS_320(port->board) && baud >= 921600)
+               return -1;
 
-       if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
-           (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
-               if (baud >= 921600L)
-                       return (-1);
-       }
        baud = MoxaPortSetBaud(port, baud);
 
        if (termio->c_iflag & (IXON | IXOFF | IXANY)) {
@@ -2081,51 +1891,37 @@ int MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud)
                moxa_wait_finish(ofsAddr);
 
        }
-       return (baud);
+       return baud;
 }
 
-int MoxaPortGetLineOut(int port, int *dtrState, int *rtsState)
+static int MoxaPortGetLineOut(struct moxa_port *port, int *dtrState,
+               int *rtsState)
 {
+       if (dtrState)
+               *dtrState = !!(port->lineCtrl & DTR_ON);
+       if (rtsState)
+               *rtsState = !!(port->lineCtrl & RTS_ON);
 
-       if (!MoxaPortIsValid(port))
-               return (-1);
-       if (dtrState) {
-               if (moxa_ports[port].lineCtrl & DTR_ON)
-                       *dtrState = 1;
-               else
-                       *dtrState = 0;
-       }
-       if (rtsState) {
-               if (moxa_ports[port].lineCtrl & RTS_ON)
-                       *rtsState = 1;
-               else
-                       *rtsState = 0;
-       }
-       return (0);
+       return 0;
 }
 
-void MoxaPortLineCtrl(int port, int dtr, int rts)
+static void MoxaPortLineCtrl(struct moxa_port *port, int dtr, int rts)
 {
-       void __iomem *ofsAddr;
-       int mode;
+       u8 mode = 0;
 
-       ofsAddr = moxa_ports[port].tableAddr;
-       mode = 0;
        if (dtr)
                mode |= DTR_ON;
        if (rts)
                mode |= RTS_ON;
-       moxa_ports[port].lineCtrl = mode;
-       moxafunc(ofsAddr, FC_LineControl, mode);
+       port->lineCtrl = mode;
+       moxafunc(port->tableAddr, FC_LineControl, mode);
 }
 
-void MoxaPortFlowCtrl(int port, int rts, int cts, int txflow, int rxflow, int txany)
+static void MoxaPortFlowCtrl(struct moxa_port *port, int rts, int cts,
+               int txflow, int rxflow, int txany)
 {
-       void __iomem *ofsAddr;
-       int mode;
+       int mode = 0;
 
-       ofsAddr = moxa_ports[port].tableAddr;
-       mode = 0;
        if (rts)
                mode |= RTS_FlowCtl;
        if (cts)
@@ -2136,81 +1932,50 @@ void MoxaPortFlowCtrl(int port, int rts, int cts, int txflow, int rxflow, int tx
                mode |= Rx_FlowCtl;
        if (txany)
                mode |= IXM_IXANY;
-       moxafunc(ofsAddr, FC_SetFlowCtl, mode);
+       moxafunc(port->tableAddr, FC_SetFlowCtl, mode);
 }
 
-int MoxaPortLineStatus(int port)
+static int MoxaPortLineStatus(struct moxa_port *port)
 {
        void __iomem *ofsAddr;
        int val;
 
-       ofsAddr = moxa_ports[port].tableAddr;
-       if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
-           (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
+       ofsAddr = port->tableAddr;
+       if (MOXA_IS_320(port->board)) {
                moxafunc(ofsAddr, FC_LineStatus, 0);
                val = readw(ofsAddr + FuncArg);
        } else {
                val = readw(ofsAddr + FlagStat) >> 4;
        }
        val &= 0x0B;
-       if (val & 8) {
+       if (val & 8)
                val |= 4;
-               if ((moxa_ports[port].DCDState & DCD_oldstate) == 0)
-                       moxa_ports[port].DCDState = (DCD_oldstate | DCD_changed);
-       } else {
-               if (moxa_ports[port].DCDState & DCD_oldstate)
-                       moxa_ports[port].DCDState = DCD_changed;
-       }
+       spin_lock_bh(&moxa_lock);
+       moxa_new_dcdstate(port, val & 8);
+       spin_unlock_bh(&moxa_lock);
        val &= 7;
-       return (val);
-}
-
-int MoxaPortDCDChange(int port)
-{
-       int n;
-
-       if (moxa_ports[port].chkPort == 0)
-               return (0);
-       n = moxa_ports[port].DCDState;
-       moxa_ports[port].DCDState &= ~DCD_changed;
-       n &= DCD_changed;
-       return (n);
-}
-
-int MoxaPortDCDON(int port)
-{
-       int n;
-
-       if (moxa_ports[port].chkPort == 0)
-               return (0);
-       if (moxa_ports[port].DCDState & DCD_oldstate)
-               n = 1;
-       else
-               n = 0;
-       return (n);
+       return val;
 }
 
-int MoxaPortWriteData(int port, unsigned char * buffer, int len)
+static int MoxaPortWriteData(struct moxa_port *port,
+               const unsigned char *buffer, int len)
 {
-       int c, total, i;
-       ushort tail;
-       int cnt;
-       ushort head, tx_mask, spage, epage;
-       ushort pageno, pageofs, bufhead;
        void __iomem *baseAddr, *ofsAddr, *ofs;
+       unsigned int c, total;
+       u16 head, tail, tx_mask, spage, epage;
+       u16 pageno, pageofs, bufhead;
 
-       ofsAddr = moxa_ports[port].tableAddr;
-       baseAddr = moxa_boards[port / MAX_PORTS_PER_BOARD].basemem;
+       ofsAddr = port->tableAddr;
+       baseAddr = port->board->basemem;
        tx_mask = readw(ofsAddr + TX_mask);
        spage = readw(ofsAddr + Page_txb);
        epage = readw(ofsAddr + EndPage_txb);
        tail = readw(ofsAddr + TXwptr);
        head = readw(ofsAddr + TXrptr);
-       c = (head > tail) ? (head - tail - 1)
-           : (head - tail + tx_mask);
+       c = (head > tail) ? (head - tail - 1) : (head - tail + tx_mask);
        if (c > len)
                c = len;
-       moxaLog.txcnt[port] += c;
+       moxaLog.txcnt[port->tty->index] += c;
        total = c;
        if (spage == epage) {
                bufhead = readw(ofsAddr + Ofs_txb);
@@ -2222,249 +1987,179 @@ int MoxaPortWriteData(int port, unsigned char * buffer, int len)
                                len = tx_mask + 1 - tail;
                        len = (c > len) ? len : c;
                        ofs = baseAddr + DynPage_addr + bufhead + tail;
-                       for (i = 0; i < len; i++)
-                               writeb(*buffer++, ofs + i);
+                       memcpy_toio(ofs, buffer, len);
+                       buffer += len;
                        tail = (tail + len) & tx_mask;
                        c -= len;
                }
-               writew(tail, ofsAddr + TXwptr);
        } else {
-               len = c;
                pageno = spage + (tail >> 13);
                pageofs = tail & Page_mask;
-               do {
-                       cnt = Page_size - pageofs;
-                       if (cnt > c)
-                               cnt = c;
-                       c -= cnt;
+               while (c > 0) {
+                       len = Page_size - pageofs;
+                       if (len > c)
+                               len = c;
                        writeb(pageno, baseAddr + Control_reg);
                        ofs = baseAddr + DynPage_addr + pageofs;
-                       for (i = 0; i < cnt; i++)
-                               writeb(*buffer++, ofs + i);
-                       if (c == 0) {
-                               writew((tail + len) & tx_mask, ofsAddr + TXwptr);
-                               break;
-                       }
+                       memcpy_toio(ofs, buffer, len);
+                       buffer += len;
                        if (++pageno == epage)
                                pageno = spage;
                        pageofs = 0;
-               } while (1);
+                       c -= len;
+               }
+               tail = (tail + total) & tx_mask;
        }
+       writew(tail, ofsAddr + TXwptr);
        writeb(1, ofsAddr + CD180TXirq);        /* start to send */
-       return (total);
+       return total;
 }
 
-int MoxaPortReadData(int port, struct tty_struct *tty)
+static int MoxaPortReadData(struct moxa_port *port)
 {
-       register ushort head, pageofs;
-       int i, count, cnt, len, total, remain;
-       ushort tail, rx_mask, spage, epage;
-       ushort pageno, bufhead;
+       struct tty_struct *tty = port->tty;
+       unsigned char *dst;
        void __iomem *baseAddr, *ofsAddr, *ofs;
+       unsigned int count, len, total;
+       u16 tail, rx_mask, spage, epage;
+       u16 pageno, pageofs, bufhead, head;
 
-       ofsAddr = moxa_ports[port].tableAddr;
-       baseAddr = moxa_boards[port / MAX_PORTS_PER_BOARD].basemem;
+       ofsAddr = port->tableAddr;
+       baseAddr = port->board->basemem;
        head = readw(ofsAddr + RXrptr);
        tail = readw(ofsAddr + RXwptr);
        rx_mask = readw(ofsAddr + RX_mask);
        spage = readw(ofsAddr + Page_rxb);
        epage = readw(ofsAddr + EndPage_rxb);
-       count = (tail >= head) ? (tail - head)
-           : (tail - head + rx_mask + 1);
+       count = (tail >= head) ? (tail - head) : (tail - head + rx_mask + 1);
        if (count == 0)
                return 0;
 
        total = count;
-       remain = count - total;
-       moxaLog.rxcnt[port] += total;
-       count = total;
+       moxaLog.rxcnt[tty->index] += total;
        if (spage == epage) {
                bufhead = readw(ofsAddr + Ofs_rxb);
                writew(spage, baseAddr + Control_reg);
                while (count > 0) {
-                       if (tail >= head)
-                               len = tail - head;
-                       else
-                               len = rx_mask + 1 - head;
-                       len = (count > len) ? len : count;
                        ofs = baseAddr + DynPage_addr + bufhead + head;
-                       for (i = 0; i < len; i++)
-                               tty_insert_flip_char(tty, readb(ofs + i), TTY_NORMAL);
+                       len = (tail >= head) ? (tail - head) :
+                                       (rx_mask + 1 - head);
+                       len = tty_prepare_flip_string(tty, &dst,
+                                       min(len, count));
+                       memcpy_fromio(dst, ofs, len);
                        head = (head + len) & rx_mask;
                        count -= len;
                }
-               writew(head, ofsAddr + RXrptr);
        } else {
-               len = count;
                pageno = spage + (head >> 13);
                pageofs = head & Page_mask;
-               do {
-                       cnt = Page_size - pageofs;
-                       if (cnt > count)
-                               cnt = count;
-                       count -= cnt;
+               while (count > 0) {
                        writew(pageno, baseAddr + Control_reg);
                        ofs = baseAddr + DynPage_addr + pageofs;
-                       for (i = 0; i < cnt; i++)
-                               tty_insert_flip_char(tty, readb(ofs + i), TTY_NORMAL);
-                       if (count == 0) {
-                               writew((head + len) & rx_mask, ofsAddr + RXrptr);
-                               break;
-                       }
-                       if (++pageno == epage)
+                       len = tty_prepare_flip_string(tty, &dst,
+                                       min(Page_size - pageofs, count));
+                       memcpy_fromio(dst, ofs, len);
+
+                       count -= len;
+                       pageofs = (pageofs + len) & Page_mask;
+                       if (pageofs == 0 && ++pageno == epage)
                                pageno = spage;
-                       pageofs = 0;
-               } while (1);
+               }
+               head = (head + total) & rx_mask;
        }
-       if ((readb(ofsAddr + FlagStat) & Xoff_state) && (remain < LowWater)) {
+       writew(head, ofsAddr + RXrptr);
+       if (readb(ofsAddr + FlagStat) & Xoff_state) {
                moxaLowWaterChk = 1;
-               moxa_ports[port].lowChkFlag = 1;
+               port->lowChkFlag = 1;
        }
-       return (total);
+       return total;
 }
 
 
-int MoxaPortTxQueue(int port)
+static int MoxaPortTxQueue(struct moxa_port *port)
 {
-       void __iomem *ofsAddr;
-       ushort rptr, wptr, mask;
-       int len;
+       void __iomem *ofsAddr = port->tableAddr;
+       u16 rptr, wptr, mask;
 
-       ofsAddr = moxa_ports[port].tableAddr;
        rptr = readw(ofsAddr + TXrptr);
        wptr = readw(ofsAddr + TXwptr);
        mask = readw(ofsAddr + TX_mask);
-       len = (wptr - rptr) & mask;
-       return (len);
+       return (wptr - rptr) & mask;
 }
 
-int MoxaPortTxFree(int port)
+static int MoxaPortTxFree(struct moxa_port *port)
 {
-       void __iomem *ofsAddr;
-       ushort rptr, wptr, mask;
-       int len;
+       void __iomem *ofsAddr = port->tableAddr;
+       u16 rptr, wptr, mask;
 
-       ofsAddr = moxa_ports[port].tableAddr;
        rptr = readw(ofsAddr + TXrptr);
        wptr = readw(ofsAddr + TXwptr);
        mask = readw(ofsAddr + TX_mask);
-       len = mask - ((wptr - rptr) & mask);
-       return (len);
+       return mask - ((wptr - rptr) & mask);
 }
 
-int MoxaPortRxQueue(int port)
+static int MoxaPortRxQueue(struct moxa_port *port)
 {
-       void __iomem *ofsAddr;
-       ushort rptr, wptr, mask;
-       int len;
+       void __iomem *ofsAddr = port->tableAddr;
+       u16 rptr, wptr, mask;
 
-       ofsAddr = moxa_ports[port].tableAddr;
        rptr = readw(ofsAddr + RXrptr);
        wptr = readw(ofsAddr + RXwptr);
        mask = readw(ofsAddr + RX_mask);
-       len = (wptr - rptr) & mask;
-       return (len);
-}
-
-
-void MoxaPortTxDisable(int port)
-{
-       void __iomem *ofsAddr;
-
-       ofsAddr = moxa_ports[port].tableAddr;
-       moxafunc(ofsAddr, FC_SetXoffState, Magic_code);
-}
-
-void MoxaPortTxEnable(int port)
-{
-       void __iomem *ofsAddr;
-
-       ofsAddr = moxa_ports[port].tableAddr;
-       moxafunc(ofsAddr, FC_SetXonState, Magic_code);
+       return (wptr - rptr) & mask;
 }
 
-
-int MoxaPortResetBrkCnt(int port)
+static void MoxaPortTxDisable(struct moxa_port *port)
 {
-       ushort cnt;
-       cnt = moxa_ports[port].breakCnt;
-       moxa_ports[port].breakCnt = 0;
-       return (cnt);
+       moxafunc(port->tableAddr, FC_SetXoffState, Magic_code);
 }
 
-
-void MoxaPortSendBreak(int port, int ms100)
+static void MoxaPortTxEnable(struct moxa_port *port)
 {
-       void __iomem *ofsAddr;
-
-       ofsAddr = moxa_ports[port].tableAddr;
-       if (ms100) {
-               moxafunc(ofsAddr, FC_SendBreak, Magic_code);
-               msleep(ms100 * 10);
-       } else {
-               moxafunc(ofsAddr, FC_SendBreak, Magic_code);
-               msleep(250);
-       }
-       moxafunc(ofsAddr, FC_StopBreak, Magic_code);
+       moxafunc(port->tableAddr, FC_SetXonState, Magic_code);
 }
 
 static int moxa_get_serial_info(struct moxa_port *info,
-                               struct serial_struct __user *retinfo)
+               struct serial_struct __user *retinfo)
 {
-       struct serial_struct tmp;
-
-       memset(&tmp, 0, sizeof(tmp));
-       tmp.type = info->type;
-       tmp.line = info->port;
-       tmp.port = 0;
-       tmp.irq = 0;
-       tmp.flags = info->asyncflags;
-       tmp.baud_base = 921600;
-       tmp.close_delay = info->close_delay;
-       tmp.closing_wait = info->closing_wait;
-       tmp.custom_divisor = 0;
-       tmp.hub6 = 0;
-       if(copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-               return -EFAULT;
-       return (0);
+       struct serial_struct tmp = {
+               .type = info->type,
+               .line = info->tty->index,
+               .flags = info->asyncflags,
+               .baud_base = 921600,
+               .close_delay = info->close_delay
+       };
+       return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
 }
 
 
 static int moxa_set_serial_info(struct moxa_port *info,
-                               struct serial_struct __user *new_info)
+               struct serial_struct __user *new_info)
 {
        struct serial_struct new_serial;
 
-       if(copy_from_user(&new_serial, new_info, sizeof(new_serial)))
+       if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
                return -EFAULT;
 
-       if ((new_serial.irq != 0) ||
-           (new_serial.port != 0) ||
-//           (new_serial.type != info->type) ||
-           (new_serial.custom_divisor != 0) ||
-           (new_serial.baud_base != 921600))
-               return (-EPERM);
+       if (new_serial.irq != 0 || new_serial.port != 0 ||
+                       new_serial.custom_divisor != 0 ||
+                       new_serial.baud_base != 921600)
+               return -EPERM;
 
        if (!capable(CAP_SYS_ADMIN)) {
                if (((new_serial.flags & ~ASYNC_USR_MASK) !=
                     (info->asyncflags & ~ASYNC_USR_MASK)))
-                       return (-EPERM);
-       } else {
+                       return -EPERM;
+       } else
                info->close_delay = new_serial.close_delay * HZ / 100;
-               info->closing_wait = new_serial.closing_wait * HZ / 100;
-       }
 
        new_serial.flags = (new_serial.flags & ~ASYNC_FLAGS);
        new_serial.flags |= (info->asyncflags & ASYNC_FLAGS);
 
-       if (new_serial.type == PORT_16550A) {
-               MoxaSetFifo(info->port, 1);
-       } else {
-               MoxaSetFifo(info->port, 0);
-       }
+       MoxaSetFifo(info, new_serial.type == PORT_16550A);
 
        info->type = new_serial.type;
-       return (0);
+       return 0;
 }
 
 
@@ -2472,374 +2167,10 @@ static int moxa_set_serial_info(struct moxa_port *info,
 /*****************************************************************************
  *     Static local functions:                                              *
  *****************************************************************************/
-static void moxafunc(void __iomem *ofsAddr, int cmd, ushort arg)
-{
-
-       writew(arg, ofsAddr + FuncArg);
-       writew(cmd, ofsAddr + FuncCode);
-       moxa_wait_finish(ofsAddr);
-}
-
-static void moxa_wait_finish(void __iomem *ofsAddr)
-{
-       unsigned long i, j;
-
-       i = jiffies;
-       while (readw(ofsAddr + FuncCode) != 0) {
-               j = jiffies;
-               if ((j - i) > moxaFuncTout) {
-                       return;
-               }
-       }
-}
-
-static void moxa_low_water_check(void __iomem *ofsAddr)
-{
-       int len;
-       ushort rptr, wptr, mask;
-
-       if (readb(ofsAddr + FlagStat) & Xoff_state) {
-               rptr = readw(ofsAddr + RXrptr);
-               wptr = readw(ofsAddr + RXwptr);
-               mask = readw(ofsAddr + RX_mask);
-               len = (wptr - rptr) & mask;
-               if (len <= Low_water)
-                       moxafunc(ofsAddr, FC_SendXon, 0);
-       }
-}
-
-static int moxaloadbios(int cardno, unsigned char __user *tmp, int len)
-{
-       void __iomem *baseAddr;
-       int i;
-
-       if(len < 0 || len > sizeof(moxaBuff))
-               return -EINVAL;
-       if(copy_from_user(moxaBuff, tmp, len))
-               return -EFAULT;
-       baseAddr = moxa_boards[cardno].basemem;
-       writeb(HW_reset, baseAddr + Control_reg);       /* reset */
-       msleep(10);
-       for (i = 0; i < 4096; i++)
-               writeb(0, baseAddr + i);        /* clear fix page */
-       for (i = 0; i < len; i++)
-               writeb(moxaBuff[i], baseAddr + i);      /* download BIOS */
-       writeb(0, baseAddr + Control_reg);      /* restart */
-       return (0);
-}
-
-static int moxafindcard(int cardno)
-{
-       void __iomem *baseAddr;
-       ushort tmp;
-
-       baseAddr = moxa_boards[cardno].basemem;
-       switch (moxa_boards[cardno].boardType) {
-       case MOXA_BOARD_C218_ISA:
-       case MOXA_BOARD_C218_PCI:
-               if ((tmp = readw(baseAddr + C218_key)) != C218_KeyCode) {
-                       return (-1);
-               }
-               break;
-       case MOXA_BOARD_CP204J:
-               if ((tmp = readw(baseAddr + C218_key)) != CP204J_KeyCode) {
-                       return (-1);
-               }
-               break;
-       default:
-               if ((tmp = readw(baseAddr + C320_key)) != C320_KeyCode) {
-                       return (-1);
-               }
-               if ((tmp = readw(baseAddr + C320_status)) != STS_init) {
-                       return (-2);
-               }
-       }
-       return (0);
-}
-
-static int moxaload320b(int cardno, unsigned char __user *tmp, int len)
-{
-       void __iomem *baseAddr;
-       int i;
-
-       if(len < 0 || len > sizeof(moxaBuff))
-               return -EINVAL;
-       if(copy_from_user(moxaBuff, tmp, len))
-               return -EFAULT;
-       baseAddr = moxa_boards[cardno].basemem;
-       writew(len - 7168 - 2, baseAddr + C320bapi_len);
-       writeb(1, baseAddr + Control_reg);      /* Select Page 1 */
-       for (i = 0; i < 7168; i++)
-               writeb(moxaBuff[i], baseAddr + DynPage_addr + i);
-       writeb(2, baseAddr + Control_reg);      /* Select Page 2 */
-       for (i = 0; i < (len - 7168); i++)
-               writeb(moxaBuff[i + 7168], baseAddr + DynPage_addr + i);
-       return (0);
-}
-
-static int moxaloadcode(int cardno, unsigned char __user *tmp, int len)
-{
-       void __iomem *baseAddr, *ofsAddr;
-       int retval, port, i;
-
-       if(len < 0 || len > sizeof(moxaBuff))
-               return -EINVAL;
-       if(copy_from_user(moxaBuff, tmp, len))
-               return -EFAULT;
-       baseAddr = moxa_boards[cardno].basemem;
-       switch (moxa_boards[cardno].boardType) {
-       case MOXA_BOARD_C218_ISA:
-       case MOXA_BOARD_C218_PCI:
-       case MOXA_BOARD_CP204J:
-               retval = moxaloadc218(cardno, baseAddr, len);
-               if (retval)
-                       return (retval);
-               port = cardno * MAX_PORTS_PER_BOARD;
-               for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) {
-                       struct moxa_port *p = &moxa_ports[port];
-
-                       p->chkPort = 1;
-                       p->curBaud = 9600L;
-                       p->DCDState = 0;
-                       p->tableAddr = baseAddr + Extern_table + Extern_size * i;
-                       ofsAddr = p->tableAddr;
-                       writew(C218rx_mask, ofsAddr + RX_mask);
-                       writew(C218tx_mask, ofsAddr + TX_mask);
-                       writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb);
-                       writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb);
-
-                       writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb);
-                       writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb);
-
-               }
-               break;
-       default:
-               retval = moxaloadc320(cardno, baseAddr, len,
-                                     &moxa_boards[cardno].numPorts);
-               if (retval)
-                       return (retval);
-               port = cardno * MAX_PORTS_PER_BOARD;
-               for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) {
-                       struct moxa_port *p = &moxa_ports[port];
-
-                       p->chkPort = 1;
-                       p->curBaud = 9600L;
-                       p->DCDState = 0;
-                       p->tableAddr = baseAddr + Extern_table + Extern_size * i;
-                       ofsAddr = p->tableAddr;
-                       if (moxa_boards[cardno].numPorts == 8) {
-                               writew(C320p8rx_mask, ofsAddr + RX_mask);
-                               writew(C320p8tx_mask, ofsAddr + TX_mask);
-                               writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb);
-                               writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb);
-                               writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb);
-                               writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb);
-
-                       } else if (moxa_boards[cardno].numPorts == 16) {
-                               writew(C320p16rx_mask, ofsAddr + RX_mask);
-                               writew(C320p16tx_mask, ofsAddr + TX_mask);
-                               writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb);
-                               writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb);
-                               writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb);
-                               writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb);
-
-                       } else if (moxa_boards[cardno].numPorts == 24) {
-                               writew(C320p24rx_mask, ofsAddr + RX_mask);
-                               writew(C320p24tx_mask, ofsAddr + TX_mask);
-                               writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb);
-                               writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb);
-                               writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb);
-                               writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
-                       } else if (moxa_boards[cardno].numPorts == 32) {
-                               writew(C320p32rx_mask, ofsAddr + RX_mask);
-                               writew(C320p32tx_mask, ofsAddr + TX_mask);
-                               writew(C320p32tx_ofs, ofsAddr + Ofs_txb);
-                               writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb);
-                               writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb);
-                               writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb);
-                               writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
-                       }
-               }
-               break;
-       }
-       moxa_boards[cardno].loadstat = 1;
-       return (0);
-}
-
-static int moxaloadc218(int cardno, void __iomem *baseAddr, int len)
-{
-       char retry;
-       int i, j, len1, len2;
-       ushort usum, *ptr, keycode;
-
-       if (moxa_boards[cardno].boardType == MOXA_BOARD_CP204J)
-               keycode = CP204J_KeyCode;
-       else
-               keycode = C218_KeyCode;
-       usum = 0;
-       len1 = len >> 1;
-       ptr = (ushort *) moxaBuff;
-       for (i = 0; i < len1; i++)
-               usum += le16_to_cpu(*(ptr + i));
-       retry = 0;
-       do {
-               len1 = len >> 1;
-               j = 0;
-               while (len1) {
-                       len2 = (len1 > 2048) ? 2048 : len1;
-                       len1 -= len2;
-                       for (i = 0; i < len2 << 1; i++)
-                               writeb(moxaBuff[i + j], baseAddr + C218_LoadBuf + i);
-                       j += i;
-
-                       writew(len2, baseAddr + C218DLoad_len);
-                       writew(0, baseAddr + C218_key);
-                       for (i = 0; i < 100; i++) {
-                               if (readw(baseAddr + C218_key) == keycode)
-                                       break;
-                               msleep(10);
-                       }
-                       if (readw(baseAddr + C218_key) != keycode) {
-                               return (-1);
-                       }
-               }
-               writew(0, baseAddr + C218DLoad_len);
-               writew(usum, baseAddr + C218check_sum);
-               writew(0, baseAddr + C218_key);
-               for (i = 0; i < 100; i++) {
-                       if (readw(baseAddr + C218_key) == keycode)
-                               break;
-                       msleep(10);
-               }
-               retry++;
-       } while ((readb(baseAddr + C218chksum_ok) != 1) && (retry < 3));
-       if (readb(baseAddr + C218chksum_ok) != 1) {
-               return (-1);
-       }
-       writew(0, baseAddr + C218_key);
-       for (i = 0; i < 100; i++) {
-               if (readw(baseAddr + Magic_no) == Magic_code)
-                       break;
-               msleep(10);
-       }
-       if (readw(baseAddr + Magic_no) != Magic_code) {
-               return (-1);
-       }
-       writew(1, baseAddr + Disable_IRQ);
-       writew(0, baseAddr + Magic_no);
-       for (i = 0; i < 100; i++) {
-               if (readw(baseAddr + Magic_no) == Magic_code)
-                       break;
-               msleep(10);
-       }
-       if (readw(baseAddr + Magic_no) != Magic_code) {
-               return (-1);
-       }
-       moxaCard = 1;
-       moxa_boards[cardno].intNdx = baseAddr + IRQindex;
-       moxa_boards[cardno].intPend = baseAddr + IRQpending;
-       moxa_boards[cardno].intTable = baseAddr + IRQtable;
-       return (0);
-}
-
-static int moxaloadc320(int cardno, void __iomem *baseAddr, int len, int *numPorts)
-{
-       ushort usum;
-       int i, j, wlen, len2, retry;
-       ushort *uptr;
-
-       usum = 0;
-       wlen = len >> 1;
-       uptr = (ushort *) moxaBuff;
-       for (i = 0; i < wlen; i++)
-               usum += le16_to_cpu(uptr[i]);
-       retry = 0;
-       j = 0;
-       do {
-               while (wlen) {
-                       if (wlen > 2048)
-                               len2 = 2048;
-                       else
-                               len2 = wlen;
-                       wlen -= len2;
-                       len2 <<= 1;
-                       for (i = 0; i < len2; i++)
-                               writeb(moxaBuff[j + i], baseAddr + C320_LoadBuf + i);
-                       len2 >>= 1;
-                       j += i;
-                       writew(len2, baseAddr + C320DLoad_len);
-                       writew(0, baseAddr + C320_key);
-                       for (i = 0; i < 10; i++) {
-                               if (readw(baseAddr + C320_key) == C320_KeyCode)
-                                       break;
-                               msleep(10);
-                       }
-                       if (readw(baseAddr + C320_key) != C320_KeyCode)
-                               return (-1);
-               }
-               writew(0, baseAddr + C320DLoad_len);
-               writew(usum, baseAddr + C320check_sum);
-               writew(0, baseAddr + C320_key);
-               for (i = 0; i < 10; i++) {
-                       if (readw(baseAddr + C320_key) == C320_KeyCode)
-                               break;
-                       msleep(10);
-               }
-               retry++;
-       } while ((readb(baseAddr + C320chksum_ok) != 1) && (retry < 3));
-       if (readb(baseAddr + C320chksum_ok) != 1)
-               return (-1);
-       writew(0, baseAddr + C320_key);
-       for (i = 0; i < 600; i++) {
-               if (readw(baseAddr + Magic_no) == Magic_code)
-                       break;
-               msleep(10);
-       }
-       if (readw(baseAddr + Magic_no) != Magic_code)
-               return (-100);
-
-       if (moxa_boards[cardno].busType == MOXA_BUS_TYPE_PCI) {         /* ASIC board */
-               writew(0x3800, baseAddr + TMS320_PORT1);
-               writew(0x3900, baseAddr + TMS320_PORT2);
-               writew(28499, baseAddr + TMS320_CLOCK);
-       } else {
-               writew(0x3200, baseAddr + TMS320_PORT1);
-               writew(0x3400, baseAddr + TMS320_PORT2);
-               writew(19999, baseAddr + TMS320_CLOCK);
-       }
-       writew(1, baseAddr + Disable_IRQ);
-       writew(0, baseAddr + Magic_no);
-       for (i = 0; i < 500; i++) {
-               if (readw(baseAddr + Magic_no) == Magic_code)
-                       break;
-               msleep(10);
-       }
-       if (readw(baseAddr + Magic_no) != Magic_code)
-               return (-102);
-
-       j = readw(baseAddr + Module_cnt);
-       if (j <= 0)
-               return (-101);
-       *numPorts = j * 8;
-       writew(j, baseAddr + Module_no);
-       writew(0, baseAddr + Magic_no);
-       for (i = 0; i < 600; i++) {
-               if (readw(baseAddr + Magic_no) == Magic_code)
-                       break;
-               msleep(10);
-       }
-       if (readw(baseAddr + Magic_no) != Magic_code)
-               return (-102);
-       moxaCard = 1;
-       moxa_boards[cardno].intNdx = baseAddr + IRQindex;
-       moxa_boards[cardno].intPend = baseAddr + IRQpending;
-       moxa_boards[cardno].intTable = baseAddr + IRQtable;
-       return (0);
-}
 
-static void MoxaSetFifo(int port, int enable)
+static void MoxaSetFifo(struct moxa_port *port, int enable)
 {
-       void __iomem *ofsAddr = moxa_ports[port].tableAddr;
+       void __iomem *ofsAddr = port->tableAddr;
 
        if (!enable) {
                moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0);
diff --git a/drivers/char/moxa.h b/drivers/char/moxa.h
new file mode 100644 (file)
index 0000000..87d16ce
--- /dev/null
@@ -0,0 +1,304 @@
+#ifndef MOXA_H_FILE
+#define MOXA_H_FILE
+
+#define        MOXA            0x400
+#define MOXA_GET_IQUEUE        (MOXA + 1)      /* get input buffered count */
+#define MOXA_GET_OQUEUE        (MOXA + 2)      /* get output buffered count */
+#define MOXA_GETDATACOUNT       (MOXA + 23)
+#define MOXA_GET_IOQUEUE       (MOXA + 27)
+#define MOXA_FLUSH_QUEUE       (MOXA + 28)
+#define MOXA_GETMSTATUS         (MOXA + 65)
+
+/*
+ *    System Configuration
+ */
+
+#define Magic_code     0x404
+
+/*
+ *    for C218 BIOS initialization
+ */
+#define C218_ConfBase  0x800
+#define C218_status    (C218_ConfBase + 0)     /* BIOS running status    */
+#define C218_diag      (C218_ConfBase + 2)     /* diagnostic status      */
+#define C218_key       (C218_ConfBase + 4)     /* WORD (0x218 for C218) */
+#define C218DLoad_len  (C218_ConfBase + 6)     /* WORD           */
+#define C218check_sum  (C218_ConfBase + 8)     /* BYTE           */
+#define C218chksum_ok  (C218_ConfBase + 0x0a)  /* BYTE (1:ok)            */
+#define C218_TestRx    (C218_ConfBase + 0x10)  /* 8 bytes for 8 ports    */
+#define C218_TestTx    (C218_ConfBase + 0x18)  /* 8 bytes for 8 ports    */
+#define C218_RXerr     (C218_ConfBase + 0x20)  /* 8 bytes for 8 ports    */
+#define C218_ErrFlag   (C218_ConfBase + 0x28)  /* 8 bytes for 8 ports    */
+
+#define C218_LoadBuf   0x0F00
+#define C218_KeyCode   0x218
+#define CP204J_KeyCode 0x204
+
+/*
+ *    for C320 BIOS initialization
+ */
+#define C320_ConfBase  0x800
+#define C320_LoadBuf   0x0f00
+#define STS_init       0x05    /* for C320_status        */
+
+#define C320_status    C320_ConfBase + 0       /* BIOS running status    */
+#define C320_diag      C320_ConfBase + 2       /* diagnostic status      */
+#define C320_key       C320_ConfBase + 4       /* WORD (0320H for C320) */
+#define C320DLoad_len  C320_ConfBase + 6       /* WORD           */
+#define C320check_sum  C320_ConfBase + 8       /* WORD           */
+#define C320chksum_ok  C320_ConfBase + 0x0a    /* WORD (1:ok)            */
+#define C320bapi_len   C320_ConfBase + 0x0c    /* WORD           */
+#define C320UART_no    C320_ConfBase + 0x0e    /* WORD           */
+
+#define C320_KeyCode   0x320
+
+#define FixPage_addr   0x0000  /* starting addr of static page  */
+#define DynPage_addr   0x2000  /* starting addr of dynamic page */
+#define C218_start     0x3000  /* starting addr of C218 BIOS prg */
+#define Control_reg    0x1ff0  /* select page and reset control */
+#define HW_reset       0x80
+
+/*
+ *    Function Codes
+ */
+#define FC_CardReset   0x80
+#define FC_ChannelReset 1      /* C320 firmware not supported */
+#define FC_EnableCH    2
+#define FC_DisableCH   3
+#define FC_SetParam    4
+#define FC_SetMode     5
+#define FC_SetRate     6
+#define FC_LineControl 7
+#define FC_LineStatus  8
+#define FC_XmitControl 9
+#define FC_FlushQueue  10
+#define FC_SendBreak   11
+#define FC_StopBreak   12
+#define FC_LoopbackON  13
+#define FC_LoopbackOFF 14
+#define FC_ClrIrqTable 15
+#define FC_SendXon     16
+#define FC_SetTermIrq  17      /* C320 firmware not supported */
+#define FC_SetCntIrq   18      /* C320 firmware not supported */
+#define FC_SetBreakIrq 19
+#define FC_SetLineIrq  20
+#define FC_SetFlowCtl  21
+#define FC_GenIrq      22
+#define FC_InCD180     23
+#define FC_OutCD180    24
+#define FC_InUARTreg   23
+#define FC_OutUARTreg  24
+#define FC_SetXonXoff  25
+#define FC_OutCD180CCR 26
+#define FC_ExtIQueue   27
+#define FC_ExtOQueue   28
+#define FC_ClrLineIrq  29
+#define FC_HWFlowCtl   30
+#define FC_GetClockRate 35
+#define FC_SetBaud     36
+#define FC_SetDataMode  41
+#define FC_GetCCSR      43
+#define FC_GetDataError 45
+#define FC_RxControl   50
+#define FC_ImmSend     51
+#define FC_SetXonState 52
+#define FC_SetXoffState        53
+#define FC_SetRxFIFOTrig 54
+#define FC_SetTxFIFOCnt 55
+#define FC_UnixRate    56
+#define FC_UnixResetTimer 57
+
+#define        RxFIFOTrig1     0
+#define        RxFIFOTrig4     1
+#define        RxFIFOTrig8     2
+#define        RxFIFOTrig14    3
+
+/*
+ *    Dual-Ported RAM
+ */
+#define DRAM_global    0
+#define INT_data       (DRAM_global + 0)
+#define Config_base    (DRAM_global + 0x108)
+
+#define IRQindex       (INT_data + 0)
+#define IRQpending     (INT_data + 4)
+#define IRQtable       (INT_data + 8)
+
+/*
+ *    Interrupt Status
+ */
+#define IntrRx         0x01    /* receiver data O.K.             */
+#define IntrTx         0x02    /* transmit buffer empty  */
+#define IntrFunc       0x04    /* function complete              */
+#define IntrBreak      0x08    /* received break         */
+#define IntrLine       0x10    /* line status change
+                                  for transmitter                */
+#define IntrIntr       0x20    /* received INTR code             */
+#define IntrQuit       0x40    /* received QUIT code             */
+#define IntrEOF        0x80    /* received EOF code              */
+
+#define IntrRxTrigger  0x100   /* rx data count reach tigger value */
+#define IntrTxTrigger  0x200   /* tx data count below trigger value */
+
+#define Magic_no       (Config_base + 0)
+#define Card_model_no  (Config_base + 2)
+#define Total_ports    (Config_base + 4)
+#define Module_cnt     (Config_base + 8)
+#define Module_no      (Config_base + 10)
+#define Timer_10ms     (Config_base + 14)
+#define Disable_IRQ    (Config_base + 20)
+#define TMS320_PORT1   (Config_base + 22)
+#define TMS320_PORT2   (Config_base + 24)
+#define TMS320_CLOCK   (Config_base + 26)
+
+/*
+ *    DATA BUFFER in DRAM
+ */
+#define Extern_table   0x400   /* Base address of the external table
+                                  (24 words *    64) total 3K bytes
+                                  (24 words * 128) total 6K bytes */
+#define Extern_size    0x60    /* 96 bytes                       */
+#define RXrptr         0x00    /* read pointer for RX buffer     */
+#define RXwptr         0x02    /* write pointer for RX buffer    */
+#define TXrptr         0x04    /* read pointer for TX buffer     */
+#define TXwptr         0x06    /* write pointer for TX buffer    */
+#define HostStat       0x08    /* IRQ flag and general flag      */
+#define FlagStat       0x0A
+#define FlowControl    0x0C    /* B7 B6 B5 B4 B3 B2 B1 B0              */
+                               /*  x  x  x  x  |  |  |  |            */
+                               /*              |  |  |  + CTS flow   */
+                               /*              |  |  +--- RTS flow   */
+                               /*              |  +------ TX Xon/Xoff */
+                               /*              +--------- RX Xon/Xoff */
+#define Break_cnt      0x0E    /* received break count   */
+#define CD180TXirq     0x10    /* if non-0: enable TX irq        */
+#define RX_mask        0x12
+#define TX_mask        0x14
+#define Ofs_rxb        0x16
+#define Ofs_txb        0x18
+#define Page_rxb       0x1A
+#define Page_txb       0x1C
+#define EndPage_rxb    0x1E
+#define EndPage_txb    0x20
+#define Data_error     0x22
+#define RxTrigger      0x28
+#define TxTrigger      0x2a
+
+#define rRXwptr        0x34
+#define Low_water      0x36
+
+#define FuncCode       0x40
+#define FuncArg        0x42
+#define FuncArg1       0x44
+
+#define C218rx_size    0x2000  /* 8K bytes */
+#define C218tx_size    0x8000  /* 32K bytes */
+
+#define C218rx_mask    (C218rx_size - 1)
+#define C218tx_mask    (C218tx_size - 1)
+
+#define C320p8rx_size  0x2000
+#define C320p8tx_size  0x8000
+#define C320p8rx_mask  (C320p8rx_size - 1)
+#define C320p8tx_mask  (C320p8tx_size - 1)
+
+#define C320p16rx_size 0x2000
+#define C320p16tx_size 0x4000
+#define C320p16rx_mask (C320p16rx_size - 1)
+#define C320p16tx_mask (C320p16tx_size - 1)
+
+#define C320p24rx_size 0x2000
+#define C320p24tx_size 0x2000
+#define C320p24rx_mask (C320p24rx_size - 1)
+#define C320p24tx_mask (C320p24tx_size - 1)
+
+#define C320p32rx_size 0x1000
+#define C320p32tx_size 0x1000
+#define C320p32rx_mask (C320p32rx_size - 1)
+#define C320p32tx_mask (C320p32tx_size - 1)
+
+#define Page_size      0x2000U
+#define Page_mask      (Page_size - 1)
+#define C218rx_spage   3
+#define C218tx_spage   4
+#define C218rx_pageno  1
+#define C218tx_pageno  4
+#define C218buf_pageno 5
+
+#define C320p8rx_spage 3
+#define C320p8tx_spage 4
+#define C320p8rx_pgno  1
+#define C320p8tx_pgno  4
+#define C320p8buf_pgno 5
+
+#define C320p16rx_spage 3
+#define C320p16tx_spage 4
+#define C320p16rx_pgno 1
+#define C320p16tx_pgno 2
+#define C320p16buf_pgno 3
+
+#define C320p24rx_spage 3
+#define C320p24tx_spage 4
+#define C320p24rx_pgno 1
+#define C320p24tx_pgno 1
+#define C320p24buf_pgno 2
+
+#define C320p32rx_spage 3
+#define C320p32tx_ofs  C320p32rx_size
+#define C320p32tx_spage 3
+#define C320p32buf_pgno 1
+
+/*
+ *    Host Status
+ */
+#define WakeupRx       0x01
+#define WakeupTx       0x02
+#define WakeupBreak    0x08
+#define WakeupLine     0x10
+#define WakeupIntr     0x20
+#define WakeupQuit     0x40
+#define WakeupEOF      0x80    /* used in VTIME control */
+#define WakeupRxTrigger        0x100
+#define WakeupTxTrigger        0x200
+/*
+ *    Flag status
+ */
+#define Rx_over                0x01
+#define Xoff_state     0x02
+#define Tx_flowOff     0x04
+#define Tx_enable      0x08
+#define CTS_state      0x10
+#define DSR_state      0x20
+#define DCD_state      0x80
+/*
+ *    FlowControl
+ */
+#define CTS_FlowCtl    1
+#define RTS_FlowCtl    2
+#define Tx_FlowCtl     4
+#define Rx_FlowCtl     8
+#define IXM_IXANY      0x10
+
+#define LowWater       128
+
+#define DTR_ON         1
+#define RTS_ON         2
+#define CTS_ON         1
+#define DSR_ON         2
+#define DCD_ON         8
+
+/* mode definition */
+#define        MX_CS8          0x03
+#define        MX_CS7          0x02
+#define        MX_CS6          0x01
+#define        MX_CS5          0x00
+
+#define        MX_STOP1        0x00
+#define        MX_STOP15       0x04
+#define        MX_STOP2        0x08
+
+#define        MX_PARNONE      0x00
+#define        MX_PAREVEN      0x40
+#define        MX_PARODD       0xC0
+
+#endif
index ff146c2b08fd65cb6e26498923d4df8b03ab95df..fe2a95b5d3c05e36121110de446e7309098d3f6b 100644 (file)
@@ -180,7 +180,7 @@ mspec_close(struct vm_area_struct *vma)
                my_page = vdata->maddr[index];
                vdata->maddr[index] = 0;
                if (!mspec_zero_block(my_page, PAGE_SIZE))
-                       uncached_free_page(my_page);
+                       uncached_free_page(my_page, 1);
                else
                        printk(KERN_WARNING "mspec_close(): "
                               "failed to zero page %ld\n", my_page);
@@ -209,7 +209,7 @@ mspec_nopfn(struct vm_area_struct *vma, unsigned long address)
        index = (address - vdata->vm_start) >> PAGE_SHIFT;
        maddr = (volatile unsigned long) vdata->maddr[index];
        if (maddr == 0) {
-               maddr = uncached_alloc_page(numa_node_id());
+               maddr = uncached_alloc_page(numa_node_id(), 1);
                if (maddr == 0)
                        return NOPFN_OOM;
 
@@ -218,7 +218,7 @@ mspec_nopfn(struct vm_area_struct *vma, unsigned long address)
                        vdata->count++;
                        vdata->maddr[index] = maddr;
                } else {
-                       uncached_free_page(maddr);
+                       uncached_free_page(maddr, 1);
                        maddr = vdata->maddr[index];
                }
                spin_unlock(&vdata->lock);
@@ -367,7 +367,7 @@ mspec_init(void)
                                int nasid;
                                unsigned long phys;
 
-                               scratch_page[nid] = uncached_alloc_page(nid);
+                               scratch_page[nid] = uncached_alloc_page(nid, 1);
                                if (scratch_page[nid] == 0)
                                        goto free_scratch_pages;
                                phys = __pa(scratch_page[nid]);
@@ -414,7 +414,7 @@ mspec_init(void)
  free_scratch_pages:
        for_each_node(nid) {
                if (scratch_page[nid] != 0)
-                       uncached_free_page(scratch_page[nid]);
+                       uncached_free_page(scratch_page[nid], 1);
        }
        return ret;
 }
@@ -431,7 +431,7 @@ mspec_exit(void)
 
                for_each_node(nid) {
                        if (scratch_page[nid] != 0)
-                               uncached_free_page(scratch_page[nid]);
+                               uncached_free_page(scratch_page[nid], 1);
                }
        }
 }
index 68c2e923469195295ed74c028eb360e2588e9a19..4b81a85c5b53d1002252514b9e95c3cc60c0bb43 100644 (file)
@@ -307,6 +307,200 @@ static unsigned char mxser_msr[MXSER_PORTS + 1];
 static struct mxser_mon_ext mon_data_ext;
 static int mxser_set_baud_method[MXSER_PORTS + 1];
 
+static void mxser_enable_must_enchance_mode(unsigned long baseio)
+{
+       u8 oldlcr;
+       u8 efr;
+
+       oldlcr = inb(baseio + UART_LCR);
+       outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+       efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+       efr |= MOXA_MUST_EFR_EFRB_ENABLE;
+
+       outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+       outb(oldlcr, baseio + UART_LCR);
+}
+
+static void mxser_disable_must_enchance_mode(unsigned long baseio)
+{
+       u8 oldlcr;
+       u8 efr;
+
+       oldlcr = inb(baseio + UART_LCR);
+       outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+       efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+       efr &= ~MOXA_MUST_EFR_EFRB_ENABLE;
+
+       outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+       outb(oldlcr, baseio + UART_LCR);
+}
+
+static void mxser_set_must_xon1_value(unsigned long baseio, u8 value)
+{
+       u8 oldlcr;
+       u8 efr;
+
+       oldlcr = inb(baseio + UART_LCR);
+       outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+       efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+       efr &= ~MOXA_MUST_EFR_BANK_MASK;
+       efr |= MOXA_MUST_EFR_BANK0;
+
+       outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+       outb(value, baseio + MOXA_MUST_XON1_REGISTER);
+       outb(oldlcr, baseio + UART_LCR);
+}
+
+static void mxser_set_must_xoff1_value(unsigned long baseio, u8 value)
+{
+       u8 oldlcr;
+       u8 efr;
+
+       oldlcr = inb(baseio + UART_LCR);
+       outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+       efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+       efr &= ~MOXA_MUST_EFR_BANK_MASK;
+       efr |= MOXA_MUST_EFR_BANK0;
+
+       outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+       outb(value, baseio + MOXA_MUST_XOFF1_REGISTER);
+       outb(oldlcr, baseio + UART_LCR);
+}
+
+static void mxser_set_must_fifo_value(struct mxser_port *info)
+{
+       u8 oldlcr;
+       u8 efr;
+
+       oldlcr = inb(info->ioaddr + UART_LCR);
+       outb(MOXA_MUST_ENTER_ENCHANCE, info->ioaddr + UART_LCR);
+
+       efr = inb(info->ioaddr + MOXA_MUST_EFR_REGISTER);
+       efr &= ~MOXA_MUST_EFR_BANK_MASK;
+       efr |= MOXA_MUST_EFR_BANK1;
+
+       outb(efr, info->ioaddr + MOXA_MUST_EFR_REGISTER);
+       outb((u8)info->rx_high_water, info->ioaddr + MOXA_MUST_RBRTH_REGISTER);
+       outb((u8)info->rx_trigger, info->ioaddr + MOXA_MUST_RBRTI_REGISTER);
+       outb((u8)info->rx_low_water, info->ioaddr + MOXA_MUST_RBRTL_REGISTER);
+       outb(oldlcr, info->ioaddr + UART_LCR);
+}
+
+static void mxser_set_must_enum_value(unsigned long baseio, u8 value)
+{
+       u8 oldlcr;
+       u8 efr;
+
+       oldlcr = inb(baseio + UART_LCR);
+       outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+       efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+       efr &= ~MOXA_MUST_EFR_BANK_MASK;
+       efr |= MOXA_MUST_EFR_BANK2;
+
+       outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+       outb(value, baseio + MOXA_MUST_ENUM_REGISTER);
+       outb(oldlcr, baseio + UART_LCR);
+}
+
+static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId)
+{
+       u8 oldlcr;
+       u8 efr;
+
+       oldlcr = inb(baseio + UART_LCR);
+       outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+       efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+       efr &= ~MOXA_MUST_EFR_BANK_MASK;
+       efr |= MOXA_MUST_EFR_BANK2;
+
+       outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+       *pId = inb(baseio + MOXA_MUST_HWID_REGISTER);
+       outb(oldlcr, baseio + UART_LCR);
+}
+
+static void SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(unsigned long baseio)
+{
+       u8 oldlcr;
+       u8 efr;
+
+       oldlcr = inb(baseio + UART_LCR);
+       outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+       efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+       efr &= ~MOXA_MUST_EFR_SF_MASK;
+
+       outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+       outb(oldlcr, baseio + UART_LCR);
+}
+
+static void mxser_enable_must_tx_software_flow_control(unsigned long baseio)
+{
+       u8 oldlcr;
+       u8 efr;
+
+       oldlcr = inb(baseio + UART_LCR);
+       outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+       efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+       efr &= ~MOXA_MUST_EFR_SF_TX_MASK;
+       efr |= MOXA_MUST_EFR_SF_TX1;
+
+       outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+       outb(oldlcr, baseio + UART_LCR);
+}
+
+static void mxser_disable_must_tx_software_flow_control(unsigned long baseio)
+{
+       u8 oldlcr;
+       u8 efr;
+
+       oldlcr = inb(baseio + UART_LCR);
+       outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+       efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+       efr &= ~MOXA_MUST_EFR_SF_TX_MASK;
+
+       outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+       outb(oldlcr, baseio + UART_LCR);
+}
+
+static void mxser_enable_must_rx_software_flow_control(unsigned long baseio)
+{
+       u8 oldlcr;
+       u8 efr;
+
+       oldlcr = inb(baseio + UART_LCR);
+       outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+       efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+       efr &= ~MOXA_MUST_EFR_SF_RX_MASK;
+       efr |= MOXA_MUST_EFR_SF_RX1;
+
+       outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+       outb(oldlcr, baseio + UART_LCR);
+}
+
+static void mxser_disable_must_rx_software_flow_control(unsigned long baseio)
+{
+       u8 oldlcr;
+       u8 efr;
+
+       oldlcr = inb(baseio + UART_LCR);
+       outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+       efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+       efr &= ~MOXA_MUST_EFR_SF_RX_MASK;
+
+       outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+       outb(oldlcr, baseio + UART_LCR);
+}
+
 #ifdef CONFIG_PCI
 static int __devinit CheckIsMoxaMust(unsigned long io)
 {
@@ -314,16 +508,16 @@ static int __devinit CheckIsMoxaMust(unsigned long io)
        int i;
 
        outb(0, io + UART_LCR);
-       DISABLE_MOXA_MUST_ENCHANCE_MODE(io);
+       mxser_disable_must_enchance_mode(io);
        oldmcr = inb(io + UART_MCR);
        outb(0, io + UART_MCR);
-       SET_MOXA_MUST_XON1_VALUE(io, 0x11);
+       mxser_set_must_xon1_value(io, 0x11);
        if ((hwid = inb(io + UART_MCR)) != 0) {
                outb(oldmcr, io + UART_MCR);
                return MOXA_OTHER_UART;
        }
 
-       GET_MOXA_MUST_HARDWARE_ID(io, &hwid);
+       mxser_get_must_hardware_id(io, &hwid);
        for (i = 1; i < UART_INFO_NUM; i++) { /* 0 = OTHER_UART */
                if (hwid == Gpci_uart_info[i].type)
                        return (int)hwid;
@@ -494,10 +688,10 @@ static int mxser_set_baud(struct mxser_port *info, long newspd)
                } else
                        quot /= newspd;
 
-               SET_MOXA_MUST_ENUM_VALUE(info->ioaddr, quot);
+               mxser_set_must_enum_value(info->ioaddr, quot);
        } else
 #endif
-               SET_MOXA_MUST_ENUM_VALUE(info->ioaddr, 0);
+               mxser_set_must_enum_value(info->ioaddr, 0);
 
        return 0;
 }
@@ -553,14 +747,14 @@ static int mxser_change_speed(struct mxser_port *info,
                if (info->board->chip_flag) {
                        fcr = UART_FCR_ENABLE_FIFO;
                        fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
-                       SET_MOXA_MUST_FIFO_VALUE(info);
+                       mxser_set_must_fifo_value(info);
                } else
                        fcr = 0;
        } else {
                fcr = UART_FCR_ENABLE_FIFO;
                if (info->board->chip_flag) {
                        fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
-                       SET_MOXA_MUST_FIFO_VALUE(info);
+                       mxser_set_must_fifo_value(info);
                } else {
                        switch (info->rx_trigger) {
                        case 1:
@@ -657,17 +851,21 @@ static int mxser_change_speed(struct mxser_port *info,
                }
        }
        if (info->board->chip_flag) {
-               SET_MOXA_MUST_XON1_VALUE(info->ioaddr, START_CHAR(info->tty));
-               SET_MOXA_MUST_XOFF1_VALUE(info->ioaddr, STOP_CHAR(info->tty));
+               mxser_set_must_xon1_value(info->ioaddr, START_CHAR(info->tty));
+               mxser_set_must_xoff1_value(info->ioaddr, STOP_CHAR(info->tty));
                if (I_IXON(info->tty)) {
-                       ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
+                       mxser_enable_must_rx_software_flow_control(
+                                       info->ioaddr);
                } else {
-                       DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
+                       mxser_disable_must_rx_software_flow_control(
+                                       info->ioaddr);
                }
                if (I_IXOFF(info->tty)) {
-                       ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
+                       mxser_enable_must_tx_software_flow_control(
+                                       info->ioaddr);
                } else {
-                       DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
+                       mxser_disable_must_tx_software_flow_control(
+                                       info->ioaddr);
                }
        }
 
@@ -927,6 +1125,27 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)
        return 0;
 }
 
+static void mxser_flush_buffer(struct tty_struct *tty)
+{
+       struct mxser_port *info = tty->driver_data;
+       char fcr;
+       unsigned long flags;
+
+
+       spin_lock_irqsave(&info->slock, flags);
+       info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+
+       fcr = inb(info->ioaddr + UART_FCR);
+       outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
+               info->ioaddr + UART_FCR);
+       outb(fcr, info->ioaddr + UART_FCR);
+
+       spin_unlock_irqrestore(&info->slock, flags);
+
+       tty_wakeup(tty);
+}
+
+
 /*
  * This routine is called when the serial port gets closed.  First, we
  * wait for the last remaining data to be sent.  Then, we unlink its
@@ -1013,9 +1232,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
        }
        mxser_shutdown(info);
 
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
-
+       mxser_flush_buffer(tty);
        tty_ldisc_flush(tty);
 
        tty->closing = 0;
@@ -1072,16 +1289,16 @@ static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int cou
        return total;
 }
 
-static void mxser_put_char(struct tty_struct *tty, unsigned char ch)
+static int mxser_put_char(struct tty_struct *tty, unsigned char ch)
 {
        struct mxser_port *info = tty->driver_data;
        unsigned long flags;
 
        if (!info->xmit_buf)
-               return;
+               return 0;
 
        if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
-               return;
+               return 0;
 
        spin_lock_irqsave(&info->slock, flags);
        info->xmit_buf[info->xmit_head++] = ch;
@@ -1099,6 +1316,7 @@ static void mxser_put_char(struct tty_struct *tty, unsigned char ch)
                        spin_unlock_irqrestore(&info->slock, flags);
                }
        }
+       return 1;
 }
 
 
@@ -1142,26 +1360,6 @@ static int mxser_chars_in_buffer(struct tty_struct *tty)
        return info->xmit_cnt;
 }
 
-static void mxser_flush_buffer(struct tty_struct *tty)
-{
-       struct mxser_port *info = tty->driver_data;
-       char fcr;
-       unsigned long flags;
-
-
-       spin_lock_irqsave(&info->slock, flags);
-       info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-
-       fcr = inb(info->ioaddr + UART_FCR);
-       outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
-               info->ioaddr + UART_FCR);
-       outb(fcr, info->ioaddr + UART_FCR);
-
-       spin_unlock_irqrestore(&info->slock, flags);
-
-       tty_wakeup(tty);
-}
-
 /*
  * ------------------------------------------------------------
  * friends of mxser_ioctl()
@@ -1460,6 +1658,7 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
        struct mxser_port *port;
        int result, status;
        unsigned int i, j;
+       int ret = 0;
 
        switch (cmd) {
        case MOXA_GET_MAJOR:
@@ -1467,18 +1666,21 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
 
        case MOXA_CHKPORTENABLE:
                result = 0;
-
+               lock_kernel();
                for (i = 0; i < MXSER_BOARDS; i++)
                        for (j = 0; j < MXSER_PORTS_PER_BOARD; j++)
                                if (mxser_boards[i].ports[j].ioaddr)
                                        result |= (1 << i);
-
+               unlock_kernel();
                return put_user(result, (unsigned long __user *)argp);
        case MOXA_GETDATACOUNT:
+               lock_kernel();
                if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log)))
-                       return -EFAULT;
-               return 0;
+                       ret = -EFAULT;
+               unlock_kernel();
+               return ret;
        case MOXA_GETMSTATUS:
+               lock_kernel();
                for (i = 0; i < MXSER_BOARDS; i++)
                        for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) {
                                port = &mxser_boards[i].ports[j];
@@ -1515,6 +1717,7 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
                                else
                                        GMStatus[i].cts = 0;
                        }
+               unlock_kernel();
                if (copy_to_user(argp, GMStatus,
                                sizeof(struct mxser_mstatus) * MXSER_PORTS))
                        return -EFAULT;
@@ -1524,7 +1727,8 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
                unsigned long opmode;
                unsigned cflag, iflag;
 
-               for (i = 0; i < MXSER_BOARDS; i++)
+               lock_kernel();
+               for (i = 0; i < MXSER_BOARDS; i++) {
                        for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) {
                                port = &mxser_boards[i].ports[j];
                                if (!port->ioaddr)
@@ -1589,13 +1793,14 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
                                mon_data_ext.iftype[i] = opmode;
 
                        }
-                       if (copy_to_user(argp, &mon_data_ext,
-                                               sizeof(mon_data_ext)))
-                               return -EFAULT;
-
-                       return 0;
-
-       } default:
+               }
+               unlock_kernel();
+               if (copy_to_user(argp, &mon_data_ext,
+                                       sizeof(mon_data_ext)))
+                       return -EFAULT;
+               return 0;
+       }
+       default:
                return -ENOIOCTLCMD;
        }
        return 0;
@@ -1651,16 +1856,20 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
                                        opmode != RS422_MODE &&
                                        opmode != RS485_4WIRE_MODE)
                                return -EFAULT;
+                       lock_kernel();
                        mask = ModeMask[p];
                        shiftbit = p * 2;
                        val = inb(info->opmode_ioaddr);
                        val &= mask;
                        val |= (opmode << shiftbit);
                        outb(val, info->opmode_ioaddr);
+                       unlock_kernel();
                } else {
+                       lock_kernel();
                        shiftbit = p * 2;
                        opmode = inb(info->opmode_ioaddr) >> shiftbit;
                        opmode &= OP_MODE_MASK;
+                       unlock_kernel();
                        if (put_user(opmode, (int __user *)argp))
                                return -EFAULT;
                }
@@ -1687,19 +1896,18 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
                tty_wait_until_sent(tty, 0);
                mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
                return 0;
-       case TIOCGSOFTCAR:
-               return put_user(!!C_CLOCAL(tty), (unsigned long __user *)argp);
-       case TIOCSSOFTCAR:
-               if (get_user(arg, (unsigned long __user *)argp))
-                       return -EFAULT;
-               tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
-               return 0;
        case TIOCGSERIAL:
-               return mxser_get_serial_info(info, argp);
+               lock_kernel();
+               retval = mxser_get_serial_info(info, argp);
+               unlock_kernel();
+               return retval;
        case TIOCSSERIAL:
-               return mxser_set_serial_info(info, argp);
+               lock_kernel();
+               retval = mxser_set_serial_info(info, argp);
+               unlock_kernel();
+               return retval;
        case TIOCSERGETLSR:     /* Get line status register */
-               return mxser_get_lsr_info(info, argp);
+               return  mxser_get_lsr_info(info, argp);
                /*
                 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
                 * - mask passed in arg for lines of interest
@@ -1746,24 +1954,27 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
        case MOXA_HighSpeedOn:
                return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
        case MOXA_SDS_RSTICOUNTER:
+               lock_kernel();
                info->mon_data.rxcnt = 0;
                info->mon_data.txcnt = 0;
+               unlock_kernel();
                return 0;
 
        case MOXA_ASPP_OQUEUE:{
                int len, lsr;
 
+               lock_kernel();
                len = mxser_chars_in_buffer(tty);
-
                lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT;
-
                len += (lsr ? 0 : 1);
+               unlock_kernel();
 
                return put_user(len, (int __user *)argp);
        }
        case MOXA_ASPP_MON: {
                int mcr, status;
 
+               lock_kernel();
                status = mxser_get_msr(info->ioaddr, 1, tty->index);
                mxser_check_modem_status(info, status);
 
@@ -1782,7 +1993,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
                        info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD;
                else
                        info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD;
-
+               unlock_kernel();
                if (copy_to_user(argp, &info->mon_data,
                                sizeof(struct mxser_mon)))
                        return -EFAULT;
@@ -1925,7 +2136,8 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi
 
                if (info->board->chip_flag) {
                        spin_lock_irqsave(&info->slock, flags);
-                       DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr);
+                       mxser_disable_must_rx_software_flow_control(
+                                       info->ioaddr);
                        spin_unlock_irqrestore(&info->slock, flags);
                }
 
@@ -1979,6 +2191,7 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
                timeout, char_time);
        printk("jiff=%lu...", jiffies);
 #endif
+       lock_kernel();
        while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) {
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
                printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
@@ -1990,6 +2203,7 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
                        break;
        }
        set_current_state(TASK_RUNNING);
+       unlock_kernel();
 
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
        printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
@@ -2342,7 +2556,7 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
 
                /* Enhance mode enabled here */
                if (brd->chip_flag != MOXA_OTHER_UART)
-                       ENABLE_MOXA_MUST_ENCHANCE_MODE(info->ioaddr);
+                       mxser_enable_must_enchance_mode(info->ioaddr);
 
                info->flags = ASYNC_SHARE_IRQ;
                info->type = brd->uart_type;
index 844171115954701dd6055fd6d5be9906843486fb..41878a69203d72ae1d3b52830868ff561f1ca83e 100644 (file)
 /* Rx software flow control mask */
 #define MOXA_MUST_EFR_SF_RX_MASK       0x03
 
-#define ENABLE_MOXA_MUST_ENCHANCE_MODE(baseio) do {            \
-       u8      __oldlcr, __efr;                                \
-       __oldlcr = inb((baseio)+UART_LCR);                      \
-       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
-       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);           \
-       __efr |= MOXA_MUST_EFR_EFRB_ENABLE;                     \
-       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);           \
-       outb(__oldlcr, (baseio)+UART_LCR);                      \
-} while (0)
-
-#define DISABLE_MOXA_MUST_ENCHANCE_MODE(baseio) do {           \
-       u8      __oldlcr, __efr;                                \
-       __oldlcr = inb((baseio)+UART_LCR);                      \
-       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
-       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);           \
-       __efr &= ~MOXA_MUST_EFR_EFRB_ENABLE;                    \
-       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);           \
-       outb(__oldlcr, (baseio)+UART_LCR);                      \
-} while (0)
-
-#define SET_MOXA_MUST_XON1_VALUE(baseio, Value) do {           \
-       u8      __oldlcr, __efr;                                \
-       __oldlcr = inb((baseio)+UART_LCR);                      \
-       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
-       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);           \
-       __efr &= ~MOXA_MUST_EFR_BANK_MASK;                      \
-       __efr |= MOXA_MUST_EFR_BANK0;                           \
-       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);           \
-       outb((u8)(Value), (baseio)+MOXA_MUST_XON1_REGISTER);    \
-       outb(__oldlcr, (baseio)+UART_LCR);                      \
-} while (0)
-
-#define SET_MOXA_MUST_XOFF1_VALUE(baseio, Value) do {          \
-       u8      __oldlcr, __efr;                                \
-       __oldlcr = inb((baseio)+UART_LCR);                      \
-       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
-       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);           \
-       __efr &= ~MOXA_MUST_EFR_BANK_MASK;                      \
-       __efr |= MOXA_MUST_EFR_BANK0;                           \
-       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);           \
-       outb((u8)(Value), (baseio)+MOXA_MUST_XOFF1_REGISTER);   \
-       outb(__oldlcr, (baseio)+UART_LCR);                      \
-} while (0)
-
-#define SET_MOXA_MUST_FIFO_VALUE(info) do {                    \
-       u8      __oldlcr, __efr;                                \
-       __oldlcr = inb((info)->ioaddr+UART_LCR);                \
-       outb(MOXA_MUST_ENTER_ENCHANCE, (info)->ioaddr+UART_LCR);\
-       __efr = inb((info)->ioaddr+MOXA_MUST_EFR_REGISTER);     \
-       __efr &= ~MOXA_MUST_EFR_BANK_MASK;                      \
-       __efr |= MOXA_MUST_EFR_BANK1;                           \
-       outb(__efr, (info)->ioaddr+MOXA_MUST_EFR_REGISTER);     \
-       outb((u8)((info)->rx_high_water), (info)->ioaddr+       \
-                       MOXA_MUST_RBRTH_REGISTER);              \
-       outb((u8)((info)->rx_trigger), (info)->ioaddr+          \
-                       MOXA_MUST_RBRTI_REGISTER);              \
-       outb((u8)((info)->rx_low_water), (info)->ioaddr+        \
-                       MOXA_MUST_RBRTL_REGISTER);              \
-       outb(__oldlcr, (info)->ioaddr+UART_LCR);                \
-} while (0)
-
-#define SET_MOXA_MUST_ENUM_VALUE(baseio, Value) do {           \
-       u8      __oldlcr, __efr;                                \
-       __oldlcr = inb((baseio)+UART_LCR);                      \
-       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
-       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);           \
-       __efr &= ~MOXA_MUST_EFR_BANK_MASK;                      \
-       __efr |= MOXA_MUST_EFR_BANK2;                           \
-       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);           \
-       outb((u8)(Value), (baseio)+MOXA_MUST_ENUM_REGISTER);    \
-       outb(__oldlcr, (baseio)+UART_LCR);                      \
-} while (0)
-
-#define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) do {            \
-       u8      __oldlcr, __efr;                                \
-       __oldlcr = inb((baseio)+UART_LCR);                      \
-       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
-       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);           \
-       __efr &= ~MOXA_MUST_EFR_BANK_MASK;                      \
-       __efr |= MOXA_MUST_EFR_BANK2;                           \
-       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);           \
-       *pId = inb((baseio)+MOXA_MUST_HWID_REGISTER);           \
-       outb(__oldlcr, (baseio)+UART_LCR);                      \
-} while (0)
-
-#define SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(baseio) do {    \
-       u8      __oldlcr, __efr;                                \
-       __oldlcr = inb((baseio)+UART_LCR);                      \
-       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
-       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);           \
-       __efr &= ~MOXA_MUST_EFR_SF_MASK;                        \
-       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);           \
-       outb(__oldlcr, (baseio)+UART_LCR);                      \
-} while (0)
-
-#define ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) do { \
-       u8      __oldlcr, __efr;                                \
-       __oldlcr = inb((baseio)+UART_LCR);                      \
-       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
-       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);           \
-       __efr &= ~MOXA_MUST_EFR_SF_TX_MASK;                     \
-       __efr |= MOXA_MUST_EFR_SF_TX1;                          \
-       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);           \
-       outb(__oldlcr, (baseio)+UART_LCR);                      \
-} while (0)
-
-#define DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) do {        \
-       u8      __oldlcr, __efr;                                \
-       __oldlcr = inb((baseio)+UART_LCR);                      \
-       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
-       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);           \
-       __efr &= ~MOXA_MUST_EFR_SF_TX_MASK;                     \
-       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);           \
-       outb(__oldlcr, (baseio)+UART_LCR);                      \
-} while (0)
-
-#define ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) do { \
-       u8      __oldlcr, __efr;                                \
-       __oldlcr = inb((baseio)+UART_LCR);                      \
-       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
-       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);           \
-       __efr &= ~MOXA_MUST_EFR_SF_RX_MASK;                     \
-       __efr |= MOXA_MUST_EFR_SF_RX1;                          \
-       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);           \
-       outb(__oldlcr, (baseio)+UART_LCR);                      \
-} while (0)
-
-#define DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) do {        \
-       u8      __oldlcr, __efr;                                \
-       __oldlcr = inb((baseio)+UART_LCR);                      \
-       outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR);      \
-       __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER);           \
-       __efr &= ~MOXA_MUST_EFR_SF_RX_MASK;                     \
-       outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER);           \
-       outb(__oldlcr, (baseio)+UART_LCR);                      \
-} while (0)
-
 #endif
index 06803ed5568ccbad5c0a2c470d5c060d13b82dfc..a35bfd7ee80ecca131d37e8ea0798390ed5896d6 100644 (file)
@@ -342,12 +342,10 @@ static int n_hdlc_tty_open (struct tty_struct *tty)
 #endif
        
        /* Flush any pending characters in the driver and discipline. */
-       
        if (tty->ldisc.flush_buffer)
-               tty->ldisc.flush_buffer (tty);
+               tty->ldisc.flush_buffer(tty);
 
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer (tty);
+       tty_driver_flush_buffer(tty);
                
        if (debuglevel >= DEBUG_LEVEL_INFO)     
                printk("%s(%d)n_hdlc_tty_open() success\n",__FILE__,__LINE__);
@@ -399,7 +397,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty)
                        
                /* Send the next block of data to device */
                tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
-               actual = tty->driver->write(tty, tbuf->buf, tbuf->count);
+               actual = tty->ops->write(tty, tbuf->buf, tbuf->count);
 
                /* rollback was possible and has been done */
                if (actual == -ERESTARTSYS) {
@@ -578,26 +576,36 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
                return -EFAULT;
        }
 
+       lock_kernel();
+
        for (;;) {
-               if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
+               if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
+                       unlock_kernel();
                        return -EIO;
+               }
 
                n_hdlc = tty2n_hdlc (tty);
                if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC ||
-                        tty != n_hdlc->tty)
+                        tty != n_hdlc->tty) {
+                       unlock_kernel();
                        return 0;
+               }
 
                rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list);
                if (rbuf)
                        break;
                        
                /* no data */
-               if (file->f_flags & O_NONBLOCK)
+               if (file->f_flags & O_NONBLOCK) {
+                       unlock_kernel();
                        return -EAGAIN;
+               }
                        
                interruptible_sleep_on (&tty->read_wait);
-               if (signal_pending(current))
+               if (signal_pending(current)) {
+                       unlock_kernel();
                        return -EINTR;
+               }
        }
                
        if (rbuf->count > nr)
@@ -618,7 +626,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
                kfree(rbuf);
        else    
                n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf);
-       
+       unlock_kernel();
        return ret;
        
 }      /* end of n_hdlc_tty_read() */
@@ -661,6 +669,8 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,
                count = maxframe;
        }
        
+       lock_kernel();
+
        add_wait_queue(&tty->write_wait, &wait);
        set_current_state(TASK_INTERRUPTIBLE);
        
@@ -695,7 +705,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,
                n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf);
                n_hdlc_send_frames(n_hdlc,tty);
        }
-
+       unlock_kernel();
        return error;
        
 }      /* end of n_hdlc_tty_write() */
@@ -740,8 +750,7 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,
 
        case TIOCOUTQ:
                /* get the pending tx byte count in the driver */
-               count = tty->driver->chars_in_buffer ?
-                               tty->driver->chars_in_buffer(tty) : 0;
+               count = tty_chars_in_buffer(tty);
                /* add size of next output frame in queue */
                spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock,flags);
                if (n_hdlc->tx_buf_list.head)
index 6b918b80f73e6af785eeb34fdefa27e75ca32780..902169062332483a8449a4f68b8c69756600b544 100644 (file)
@@ -376,8 +376,9 @@ static void put_char(struct r3964_info *pInfo, unsigned char ch)
        if (tty == NULL)
                return;
 
-       if (tty->driver->put_char) {
-               tty->driver->put_char(tty, ch);
+       /* FIXME: put_char should not be called from an IRQ */
+       if (tty->ops->put_char) {
+               tty->ops->put_char(tty, ch);
        }
        pInfo->bcc ^= ch;
 }
@@ -386,12 +387,9 @@ static void flush(struct r3964_info *pInfo)
 {
        struct tty_struct *tty = pInfo->tty;
 
-       if (tty == NULL)
+       if (tty == NULL || tty->ops->flush_chars == NULL)
                return;
-
-       if (tty->driver->flush_chars) {
-               tty->driver->flush_chars(tty);
-       }
+       tty->ops->flush_chars(tty);
 }
 
 static void trigger_transmit(struct r3964_info *pInfo)
@@ -449,12 +447,11 @@ static void transmit_block(struct r3964_info *pInfo)
        struct r3964_block_header *pBlock = pInfo->tx_first;
        int room = 0;
 
-       if ((tty == NULL) || (pBlock == NULL)) {
+       if (tty == NULL || pBlock == NULL) {
                return;
        }
 
-       if (tty->driver->write_room)
-               room = tty->driver->write_room(tty);
+       room = tty_write_room(tty);
 
        TRACE_PS("transmit_block %p, room %d, length %d",
                 pBlock, room, pBlock->length);
@@ -1075,12 +1072,15 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
 
        TRACE_L("read()");
 
+       lock_kernel();
+
        pClient = findClient(pInfo, task_pid(current));
        if (pClient) {
                pMsg = remove_msg(pInfo, pClient);
                if (pMsg == NULL) {
                        /* no messages available. */
                        if (file->f_flags & O_NONBLOCK) {
+                               unlock_kernel();
                                return -EAGAIN;
                        }
                        /* block until there is a message: */
@@ -1090,8 +1090,10 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
 
                /* If we still haven't got a message, we must have been signalled */
 
-               if (!pMsg)
+               if (!pMsg) {
+                       unlock_kernel();
                        return -EINTR;
+               }
 
                /* deliver msg to client process: */
                theMsg.msg_id = pMsg->msg_id;
@@ -1102,12 +1104,15 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
                kfree(pMsg);
                TRACE_M("r3964_read - msg kfree %p", pMsg);
 
-               if (copy_to_user(buf, &theMsg, count))
+               if (copy_to_user(buf, &theMsg, count)) {
+                       unlock_kernel();
                        return -EFAULT;
+               }
 
                TRACE_PS("read - return %d", count);
                return count;
        }
+       unlock_kernel();
        return -EPERM;
 }
 
@@ -1156,6 +1161,8 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
        pHeader->locks = 0;
        pHeader->owner = NULL;
 
+       lock_kernel();
+
        pClient = findClient(pInfo, task_pid(current));
        if (pClient) {
                pHeader->owner = pClient;
@@ -1173,6 +1180,8 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
        add_tx_queue(pInfo, pHeader);
        trigger_transmit(pInfo);
 
+       unlock_kernel();
+
        return 0;
 }
 
index 0c09409fa45d4dc5f13a212c0211bab5fb307ae7..19105ec203f7afe611edfdc10c99bf50741ccecc 100644 (file)
@@ -147,10 +147,8 @@ static void put_tty_queue(unsigned char c, struct tty_struct *tty)
 
 static void check_unthrottle(struct tty_struct *tty)
 {
-       if (tty->count &&
-           test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
-           tty->driver->unthrottle)
-               tty->driver->unthrottle(tty);
+       if (tty->count)
+               tty_unthrottle(tty);
 }
 
 /**
@@ -183,22 +181,24 @@ static void reset_buffer_flags(struct tty_struct *tty)
  *     at hangup) or when the N_TTY line discipline internally has to
  *     clean the pending queue (for example some signals).
  *
- *     FIXME: tty->ctrl_status is not spinlocked and relies on
- *     lock_kernel() still.
+ *     Locking: ctrl_lock
  */
 
 static void n_tty_flush_buffer(struct tty_struct *tty)
 {
+       unsigned long flags;
        /* clear everything and unthrottle the driver */
        reset_buffer_flags(tty);
 
        if (!tty->link)
                return;
 
+       spin_lock_irqsave(&tty->ctrl_lock, flags);
        if (tty->link->packet) {
                tty->ctrl_status |= TIOCPKT_FLUSHREAD;
                wake_up_interruptible(&tty->link->read_wait);
        }
+       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
 }
 
 /**
@@ -264,17 +264,18 @@ static inline int is_continuation(unsigned char c, struct tty_struct *tty)
  *     relevant in the world today. If you ever need them, add them here.
  *
  *     Called from both the receive and transmit sides and can be called
- *     re-entrantly. Relies on lock_kernel() still.
+ *     re-entrantly. Relies on lock_kernel() for tty->column state.
  */
 
 static int opost(unsigned char c, struct tty_struct *tty)
 {
        int     space, spaces;
 
-       space = tty->driver->write_room(tty);
+       space = tty_write_room(tty);
        if (!space)
                return -1;
 
+       lock_kernel();
        if (O_OPOST(tty)) {
                switch (c) {
                case '\n':
@@ -283,7 +284,7 @@ static int opost(unsigned char c, struct tty_struct *tty)
                        if (O_ONLCR(tty)) {
                                if (space < 2)
                                        return -1;
-                               tty->driver->put_char(tty, '\r');
+                               tty_put_char(tty, '\r');
                                tty->column = 0;
                        }
                        tty->canon_column = tty->column;
@@ -305,7 +306,7 @@ static int opost(unsigned char c, struct tty_struct *tty)
                                if (space < spaces)
                                        return -1;
                                tty->column += spaces;
-                               tty->driver->write(tty, "        ", spaces);
+                               tty->ops->write(tty, "        ", spaces);
                                return 0;
                        }
                        tty->column += spaces;
@@ -322,7 +323,8 @@ static int opost(unsigned char c, struct tty_struct *tty)
                        break;
                }
        }
-       tty->driver->put_char(tty, c);
+       tty_put_char(tty, c);
+       unlock_kernel();
        return 0;
 }
 
@@ -337,7 +339,8 @@ static int opost(unsigned char c, struct tty_struct *tty)
  *     the simple cases normally found and helps to generate blocks of
  *     symbols for the console driver and thus improve performance.
  *
- *     Called from write_chan under the tty layer write lock.
+ *     Called from write_chan under the tty layer write lock. Relies
+ *     on lock_kernel for the tty->column state.
  */
 
 static ssize_t opost_block(struct tty_struct *tty,
@@ -347,12 +350,13 @@ static ssize_t opost_block(struct tty_struct *tty,
        int     i;
        const unsigned char *cp;
 
-       space = tty->driver->write_room(tty);
+       space = tty_write_room(tty);
        if (!space)
                return 0;
        if (nr > space)
                nr = space;
 
+       lock_kernel();
        for (i = 0, cp = buf; i < nr; i++, cp++) {
                switch (*cp) {
                case '\n':
@@ -384,26 +388,14 @@ static ssize_t opost_block(struct tty_struct *tty,
                }
        }
 break_out:
-       if (tty->driver->flush_chars)
-               tty->driver->flush_chars(tty);
-       i = tty->driver->write(tty, buf, i);
+       if (tty->ops->flush_chars)
+               tty->ops->flush_chars(tty);
+       i = tty->ops->write(tty, buf, i);
+       unlock_kernel();
        return i;
 }
 
 
-/**
- *     put_char        -       write character to driver
- *     @c: character (or part of unicode symbol)
- *     @tty: terminal device
- *
- *     Queue a byte to the driver layer for output
- */
-
-static inline void put_char(unsigned char c, struct tty_struct *tty)
-{
-       tty->driver->put_char(tty, c);
-}
-
 /**
  *     echo_char       -       echo characters
  *     @c: unicode byte to echo
@@ -416,8 +408,8 @@ static inline void put_char(unsigned char c, struct tty_struct *tty)
 static void echo_char(unsigned char c, struct tty_struct *tty)
 {
        if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') {
-               put_char('^', tty);
-               put_char(c ^ 0100, tty);
+               tty_put_char(tty, '^');
+               tty_put_char(tty, c ^ 0100);
                tty->column += 2;
        } else
                opost(c, tty);
@@ -426,7 +418,7 @@ static void echo_char(unsigned char c, struct tty_struct *tty)
 static inline void finish_erasing(struct tty_struct *tty)
 {
        if (tty->erasing) {
-               put_char('/', tty);
+               tty_put_char(tty, '/');
                tty->column++;
                tty->erasing = 0;
        }
@@ -510,7 +502,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
                if (L_ECHO(tty)) {
                        if (L_ECHOPRT(tty)) {
                                if (!tty->erasing) {
-                                       put_char('\\', tty);
+                                       tty_put_char(tty, '\\');
                                        tty->column++;
                                        tty->erasing = 1;
                                }
@@ -518,7 +510,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
                                echo_char(c, tty);
                                while (--cnt > 0) {
                                        head = (head+1) & (N_TTY_BUF_SIZE-1);
-                                       put_char(tty->read_buf[head], tty);
+                                       tty_put_char(tty, tty->read_buf[head]);
                                }
                        } else if (kill_type == ERASE && !L_ECHOE(tty)) {
                                echo_char(ERASE_CHAR(tty), tty);
@@ -546,22 +538,22 @@ static void eraser(unsigned char c, struct tty_struct *tty)
                                /* Now backup to that column. */
                                while (tty->column > col) {
                                        /* Can't use opost here. */
-                                       put_char('\b', tty);
+                                       tty_put_char(tty, '\b');
                                        if (tty->column > 0)
                                                tty->column--;
                                }
                        } else {
                                if (iscntrl(c) && L_ECHOCTL(tty)) {
-                                       put_char('\b', tty);
-                                       put_char(' ', tty);
-                                       put_char('\b', tty);
+                                       tty_put_char(tty, '\b');
+                                       tty_put_char(tty, ' ');
+                                       tty_put_char(tty, '\b');
                                        if (tty->column > 0)
                                                tty->column--;
                                }
                                if (!iscntrl(c) || L_ECHOCTL(tty)) {
-                                       put_char('\b', tty);
-                                       put_char(' ', tty);
-                                       put_char('\b', tty);
+                                       tty_put_char(tty, '\b');
+                                       tty_put_char(tty, ' ');
+                                       tty_put_char(tty, '\b');
                                        if (tty->column > 0)
                                                tty->column--;
                                }
@@ -592,8 +584,7 @@ static inline void isig(int sig, struct tty_struct *tty, int flush)
                kill_pgrp(tty->pgrp, sig, 1);
        if (flush || !L_NOFLSH(tty)) {
                n_tty_flush_buffer(tty);
-               if (tty->driver->flush_buffer)
-                       tty->driver->flush_buffer(tty);
+               tty_driver_flush_buffer(tty);
        }
 }
 
@@ -701,7 +692,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
 
        if (tty->stopped && !tty->flow_stopped && I_IXON(tty) &&
            ((I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty)) ||
-            c == INTR_CHAR(tty) || c == QUIT_CHAR(tty)))
+            c == INTR_CHAR(tty) || c == QUIT_CHAR(tty) || c == SUSP_CHAR(tty)))
                start_tty(tty);
 
        if (tty->closing) {
@@ -725,7 +716,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
                tty->lnext = 0;
                if (L_ECHO(tty)) {
                        if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
-                               put_char('\a', tty); /* beep if no space */
+                               tty_put_char(tty, '\a'); /* beep if no space */
                                return;
                        }
                        /* Record the column of first canon char. */
@@ -739,13 +730,6 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
                return;
        }
 
-       if (c == '\r') {
-               if (I_IGNCR(tty))
-                       return;
-               if (I_ICRNL(tty))
-                       c = '\n';
-       } else if (c == '\n' && I_INLCR(tty))
-               c = '\r';
        if (I_IXON(tty)) {
                if (c == START_CHAR(tty)) {
                        start_tty(tty);
@@ -756,6 +740,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
                        return;
                }
        }
+
        if (L_ISIG(tty)) {
                int signal;
                signal = SIGINT;
@@ -775,8 +760,7 @@ send_signal:
                         */
                        if (!L_NOFLSH(tty)) {
                                n_tty_flush_buffer(tty);
-                               if (tty->driver->flush_buffer)
-                                       tty->driver->flush_buffer(tty);
+                               tty_driver_flush_buffer(tty);
                        }
                        if (L_ECHO(tty))
                                echo_char(c, tty);
@@ -785,6 +769,15 @@ send_signal:
                        return;
                }
        }
+
+       if (c == '\r') {
+               if (I_IGNCR(tty))
+                       return;
+               if (I_ICRNL(tty))
+                       c = '\n';
+       } else if (c == '\n' && I_INLCR(tty))
+               c = '\r';
+
        if (tty->icanon) {
                if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
                    (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {
@@ -796,8 +789,8 @@ send_signal:
                        if (L_ECHO(tty)) {
                                finish_erasing(tty);
                                if (L_ECHOCTL(tty)) {
-                                       put_char('^', tty);
-                                       put_char('\b', tty);
+                                       tty_put_char(tty, '^');
+                                       tty_put_char(tty, '\b');
                                }
                        }
                        return;
@@ -818,7 +811,7 @@ send_signal:
                if (c == '\n') {
                        if (L_ECHO(tty) || L_ECHONL(tty)) {
                                if (tty->read_cnt >= N_TTY_BUF_SIZE-1)
-                                       put_char('\a', tty);
+                                       tty_put_char(tty, '\a');
                                opost('\n', tty);
                        }
                        goto handle_newline;
@@ -836,7 +829,7 @@ send_signal:
                         */
                        if (L_ECHO(tty)) {
                                if (tty->read_cnt >= N_TTY_BUF_SIZE-1)
-                                       put_char('\a', tty);
+                                       tty_put_char(tty, '\a');
                                /* Record the column of first canon char. */
                                if (tty->canon_head == tty->read_head)
                                        tty->canon_column = tty->column;
@@ -866,7 +859,7 @@ handle_newline:
        finish_erasing(tty);
        if (L_ECHO(tty)) {
                if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
-                       put_char('\a', tty); /* beep if no space */
+                       tty_put_char(tty, '\a'); /* beep if no space */
                        return;
                }
                if (c == '\n')
@@ -970,8 +963,8 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
                                break;
                        }
                }
-               if (tty->driver->flush_chars)
-                       tty->driver->flush_chars(tty);
+               if (tty->ops->flush_chars)
+                       tty->ops->flush_chars(tty);
        }
 
        n_tty_set_room(tty);
@@ -987,12 +980,8 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
         * mode.  We don't want to throttle the driver if we're in
         * canonical mode and don't have a newline yet!
         */
-       if (tty->receive_room < TTY_THRESHOLD_THROTTLE) {
-               /* check TTY_THROTTLED first so it indicates our state */
-               if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
-                   tty->driver->throttle)
-                       tty->driver->throttle(tty);
-       }
+       if (tty->receive_room < TTY_THRESHOLD_THROTTLE)
+               tty_throttle(tty);
 }
 
 int is_ignored(int sig)
@@ -1076,6 +1065,9 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
                        tty->real_raw = 0;
        }
        n_tty_set_room(tty);
+       /* The termios change make the tty ready for I/O */
+       wake_up_interruptible(&tty->write_wait);
+       wake_up_interruptible(&tty->read_wait);
 }
 
 /**
@@ -1194,6 +1186,11 @@ extern ssize_t redirected_tty_write(struct file *, const char __user *,
  *     Perform job control management checks on this file/tty descriptor
  *     and if appropriate send any needed signals and return a negative
  *     error code if action should be taken.
+ *
+ *     FIXME:
+ *     Locking: None - redirected write test is safe, testing
+ *     current->signal should possibly lock current->sighand
+ *     pgrp locking ?
  */
 
 static int job_control(struct tty_struct *tty, struct file *file)
@@ -1246,6 +1243,7 @@ static ssize_t read_chan(struct tty_struct *tty, struct file *file,
        ssize_t size;
        long timeout;
        unsigned long flags;
+       int packet;
 
 do_it_again:
 
@@ -1289,16 +1287,19 @@ do_it_again:
                if (mutex_lock_interruptible(&tty->atomic_read_lock))
                        return -ERESTARTSYS;
        }
+       packet = tty->packet;
 
        add_wait_queue(&tty->read_wait, &wait);
        while (nr) {
                /* First test for status change. */
-               if (tty->packet && tty->link->ctrl_status) {
+               if (packet && tty->link->ctrl_status) {
                        unsigned char cs;
                        if (b != buf)
                                break;
+                       spin_lock_irqsave(&tty->link->ctrl_lock, flags);
                        cs = tty->link->ctrl_status;
                        tty->link->ctrl_status = 0;
+                       spin_unlock_irqrestore(&tty->link->ctrl_lock, flags);
                        if (tty_put_user(tty, cs, b++)) {
                                retval = -EFAULT;
                                b--;
@@ -1333,6 +1334,7 @@ do_it_again:
                                retval = -ERESTARTSYS;
                                break;
                        }
+                       /* FIXME: does n_tty_set_room need locking ? */
                        n_tty_set_room(tty);
                        timeout = schedule_timeout(timeout);
                        continue;
@@ -1340,7 +1342,7 @@ do_it_again:
                __set_current_state(TASK_RUNNING);
 
                /* Deal with packet mode. */
-               if (tty->packet && b == buf) {
+               if (packet && b == buf) {
                        if (tty_put_user(tty, TIOCPKT_DATA, b++)) {
                                retval = -EFAULT;
                                b--;
@@ -1388,6 +1390,8 @@ do_it_again:
                                break;
                } else {
                        int uncopied;
+                       /* The copy function takes the read lock and handles
+                          locking internally for this case */
                        uncopied = copy_from_read_buf(tty, &b, &nr);
                        uncopied += copy_from_read_buf(tty, &b, &nr);
                        if (uncopied) {
@@ -1429,7 +1433,6 @@ do_it_again:
                 goto do_it_again;
 
        n_tty_set_room(tty);
-
        return retval;
 }
 
@@ -1492,11 +1495,11 @@ static ssize_t write_chan(struct tty_struct *tty, struct file *file,
                                        break;
                                b++; nr--;
                        }
-                       if (tty->driver->flush_chars)
-                               tty->driver->flush_chars(tty);
+                       if (tty->ops->flush_chars)
+                               tty->ops->flush_chars(tty);
                } else {
                        while (nr > 0) {
-                               c = tty->driver->write(tty, b, nr);
+                               c = tty->ops->write(tty, b, nr);
                                if (c < 0) {
                                        retval = c;
                                        goto break_out;
@@ -1533,11 +1536,6 @@ break_out:
  *
  *     This code must be sure never to sleep through a hangup.
  *     Called without the kernel lock held - fine
- *
- *     FIXME: if someone changes the VMIN or discipline settings for the
- *     terminal while another process is in poll() the poll does not
- *     recompute the new limits. Possibly set_termios should issue
- *     a read wakeup to fix this bug.
  */
 
 static unsigned int normal_poll(struct tty_struct *tty, struct file *file,
@@ -1561,9 +1559,9 @@ static unsigned int normal_poll(struct tty_struct *tty, struct file *file,
                else
                        tty->minimum_to_wake = 1;
        }
-       if (!tty_is_writelocked(tty) &&
-                       tty->driver->chars_in_buffer(tty) < WAKEUP_CHARS &&
-                       tty->driver->write_room(tty) > 0)
+       if (tty->ops->write && !tty_is_writelocked(tty) &&
+                       tty_chars_in_buffer(tty) < WAKEUP_CHARS &&
+                       tty_write_room(tty) > 0)
                mask |= POLLOUT | POLLWRNORM;
        return mask;
 }
index 6a6843a0a6742ba15b44cbf47fe93856ed71b26f..66a0f931c66ca91bf06b56e0b789edb8a0d68204 100644 (file)
@@ -73,7 +73,7 @@ do {                                                          \
        char tmp[P_BUF_SIZE];                                   \
        snprintf(tmp, sizeof(tmp), ##args);                     \
        printk(_err_flag_ "[%d] %s(): %s\n", __LINE__,          \
-               __FUNCTION__, tmp);                             \
+               __func__, tmp);                         \
 } while (0)
 
 #define DBG1(args...) D_(0x01, ##args)
@@ -1407,7 +1407,7 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
        /* Find out what card type it is */
        nozomi_get_card_type(dc);
 
-       dc->base_addr = ioremap(start, dc->card_type);
+       dc->base_addr = ioremap_nocache(start, dc->card_type);
        if (!dc->base_addr) {
                dev_err(&pdev->dev, "Unable to map card MMIO\n");
                ret = -ENODEV;
@@ -1724,6 +1724,8 @@ static int ntty_tiocmget(struct tty_struct *tty, struct file *file)
        const struct ctrl_dl *ctrl_dl = &port->ctrl_dl;
        const struct ctrl_ul *ctrl_ul = &port->ctrl_ul;
 
+       /* Note: these could change under us but it is not clear this
+          matters if so */
        return  (ctrl_ul->RTS ? TIOCM_RTS : 0) |
                (ctrl_ul->DTR ? TIOCM_DTR : 0) |
                (ctrl_dl->DCD ? TIOCM_CAR : 0) |
@@ -1849,16 +1851,6 @@ static void ntty_throttle(struct tty_struct *tty)
        spin_unlock_irqrestore(&dc->spin_mutex, flags);
 }
 
-/* just to discard single character writes */
-static void ntty_put_char(struct tty_struct *tty, unsigned char c)
-{
-       /*
-        * card does not react correct when we write single chars
-        * to the card, so we discard them
-        */
-       DBG2("PUT CHAR Function: %c", c);
-}
-
 /* Returns number of chars in buffer, called by tty layer */
 static s32 ntty_chars_in_buffer(struct tty_struct *tty)
 {
@@ -1892,7 +1884,6 @@ static const struct tty_operations tty_ops = {
        .unthrottle = ntty_unthrottle,
        .throttle = ntty_throttle,
        .chars_in_buffer = ntty_chars_in_buffer,
-       .put_char = ntty_put_char,
        .tiocmget = ntty_tiocmget,
        .tiocmset = ntty_tiocmset,
 };
index 454d7324ba40b19ef3ce1396b3f09dfb0aeaff9e..4a933d4134231cd095a859f286a0d8c7e08e434e 100644 (file)
@@ -53,7 +53,7 @@ module_param(pc_debug, int, 0600);
 #define DEBUGP(n, rdr, x, args...) do {                                \
        if (pc_debug >= (n))                                            \
                dev_printk(KERN_DEBUG, reader_to_dev(rdr), "%s:" x,     \
-                          __FUNCTION__ , ## args);                     \
+                          __func__ , ## args);                 \
        } while (0)
 #else
 #define DEBUGP(n, rdr, x, args...)
index 5f291bf739a627901dbad1fbebfe970311f538a3..035084c07329cd87bfa42da3a70e6fe624b3c201 100644 (file)
@@ -47,7 +47,7 @@ module_param(pc_debug, int, 0600);
 #define DEBUGP(n, rdr, x, args...) do {                                \
        if (pc_debug >= (n))                                            \
                dev_printk(KERN_DEBUG, reader_to_dev(rdr), "%s:" x,     \
-                          __FUNCTION__ , ##args);                      \
+                          __func__ , ##args);                  \
        } while (0)
 #else
 #define DEBUGP(n, rdr, x, args...)
index 1f978ff87fa8a2ddeece885d0773de41f071558f..fa9d3c945f311a779702cdcb33dcdf63e155deef 100644 (file)
@@ -354,32 +354,6 @@ struct ipw_rx_packet {
        unsigned int channel_idx;
 };
 
-#ifdef IPWIRELESS_STATE_DEBUG
-int ipwireless_dump_hardware_state(char *p, size_t limit,
-                                  struct ipw_hardware *hw)
-{
-       return snprintf(p, limit,
-                       "debug: initializing=%d\n"
-                       "debug: tx_ready=%d\n"
-                       "debug: tx_queued=%d\n"
-                       "debug: rx_ready=%d\n"
-                       "debug: rx_bytes_queued=%d\n"
-                       "debug: blocking_rx=%d\n"
-                       "debug: removed=%d\n"
-                       "debug: hardware.shutting_down=%d\n"
-                       "debug: to_setup=%d\n",
-                       hw->initializing,
-                       hw->tx_ready,
-                       hw->tx_queued,
-                       hw->rx_ready,
-                       hw->rx_bytes_queued,
-                       hw->blocking_rx,
-                       hw->removed,
-                       hw->shutting_down,
-                       hw->to_setup);
-}
-#endif
-
 static char *data_type(const unsigned char *buf, unsigned length)
 {
        struct nl_packet_header *hdr = (struct nl_packet_header *) buf;
index c83190ffb0e74d7642d25f14bbac2141c12d5523..19ce5eb266b19fcc5150c1b0d821547a493eda3d 100644 (file)
@@ -58,7 +58,5 @@ void ipwireless_init_hardware_v1(struct ipw_hardware *hw,
                                 void *reboot_cb_data);
 void ipwireless_init_hardware_v2_v3(struct ipw_hardware *hw);
 void ipwireless_sleep(unsigned int tenths);
-int ipwireless_dump_hardware_state(char *p, size_t limit,
-                                  struct ipw_hardware *hw);
 
 #endif
index d793e68b3e0d913030402978e46a05eedd8abf40..fe914d34f7f6f63e10e452c775d364b1d2ba1930 100644 (file)
@@ -63,21 +63,6 @@ struct ipw_network {
        struct work_struct work_go_offline;
 };
 
-
-#ifdef IPWIRELESS_STATE_DEBUG
-int ipwireless_dump_network_state(char *p, size_t limit,
-                                 struct ipw_network *network)
-{
-       return snprintf(p, limit,
-                       "debug: ppp_blocked=%d\n"
-                       "debug: outgoing_packets_queued=%d\n"
-                       "debug: network.shutting_down=%d\n",
-                       network->ppp_blocked,
-                       network->outgoing_packets_queued,
-                       network->shutting_down);
-}
-#endif
-
 static void notify_packet_sent(void *callback_data, unsigned int packet_length)
 {
        struct ipw_network *network = callback_data;
index b0e1e952fd14c7c155b7d66e28ccf02665093c63..ccacd26fc7efdf3c9836e80aa3a536190359a809 100644 (file)
@@ -49,7 +49,4 @@ void ipwireless_ppp_close(struct ipw_network *net);
 int ipwireless_ppp_channel_index(struct ipw_network *net);
 int ipwireless_ppp_unit_number(struct ipw_network *net);
 
-int ipwireless_dump_network_state(char *p, size_t limit,
-                                 struct ipw_network *net);
-
 #endif
index 583356426dfb1fb7a8c675bb82a4a0e1d3436ba6..1dd0e992c83d9ceddc777b3d6b6cc892e25044f8 100644 (file)
@@ -503,20 +503,9 @@ static void* mgslpc_get_text_ptr(void)
  * The wrappers maintain line discipline references
  * while calling into the line discipline.
  *
- * ldisc_flush_buffer - flush line discipline receive buffers
  * ldisc_receive_buf  - pass receive data to line discipline
  */
 
-static void ldisc_flush_buffer(struct tty_struct *tty)
-{
-       struct tty_ldisc *ld = tty_ldisc_ref(tty);
-       if (ld) {
-               if (ld->flush_buffer)
-                       ld->flush_buffer(tty);
-               tty_ldisc_deref(ld);
-       }
-}
-
 static void ldisc_receive_buf(struct tty_struct *tty,
                              const __u8 *data, char *flags, int count)
 {
@@ -1556,7 +1545,7 @@ static void mgslpc_change_params(MGSLPC_INFO *info)
 
 /* Add a character to the transmit buffer
  */
-static void mgslpc_put_char(struct tty_struct *tty, unsigned char ch)
+static int mgslpc_put_char(struct tty_struct *tty, unsigned char ch)
 {
        MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;
        unsigned long flags;
@@ -1567,10 +1556,10 @@ static void mgslpc_put_char(struct tty_struct *tty, unsigned char ch)
        }
 
        if (mgslpc_paranoia_check(info, tty->name, "mgslpc_put_char"))
-               return;
+               return 0;
 
        if (!info->tx_buf)
-               return;
+               return 0;
 
        spin_lock_irqsave(&info->lock,flags);
 
@@ -1583,6 +1572,7 @@ static void mgslpc_put_char(struct tty_struct *tty, unsigned char ch)
        }
 
        spin_unlock_irqrestore(&info->lock,flags);
+       return 1;
 }
 
 /* Enable transmitter so remaining characters in the
@@ -2467,10 +2457,9 @@ static void mgslpc_close(struct tty_struct *tty, struct file * filp)
        if (info->flags & ASYNC_INITIALIZED)
                mgslpc_wait_until_sent(tty, info->timeout);
 
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       mgslpc_flush_buffer(tty);
 
-       ldisc_flush_buffer(tty);
+       tty_ldisc_flush(tty);
 
        shutdown(info);
 
index 706ff34728f19382be4215e25e3052bd2b1ba371..0a05c038ae6f168236c0b5de08ddb79a9de4e45d 100644 (file)
@@ -181,6 +181,7 @@ static int pty_set_lock(struct tty_struct *tty, int __user * arg)
 static void pty_flush_buffer(struct tty_struct *tty)
 {
        struct tty_struct *to = tty->link;
+       unsigned long flags;
        
        if (!to)
                return;
@@ -189,8 +190,10 @@ static void pty_flush_buffer(struct tty_struct *tty)
                to->ldisc.flush_buffer(to);
        
        if (to->packet) {
+               spin_lock_irqsave(&tty->ctrl_lock, flags);
                tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
                wake_up_interruptible(&to->read_wait);
+               spin_unlock_irqrestore(&tty->ctrl_lock, flags);
        }
 }
 
@@ -251,6 +254,18 @@ static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file,
 static int legacy_count = CONFIG_LEGACY_PTY_COUNT;
 module_param(legacy_count, int, 0);
 
+static const struct tty_operations pty_ops_bsd = {
+       .open = pty_open,
+       .close = pty_close,
+       .write = pty_write,
+       .write_room = pty_write_room,
+       .flush_buffer = pty_flush_buffer,
+       .chars_in_buffer = pty_chars_in_buffer,
+       .unthrottle = pty_unthrottle,
+       .set_termios = pty_set_termios,
+       .ioctl = pty_bsd_ioctl,
+};
+
 static void __init legacy_pty_init(void)
 {
        if (legacy_count <= 0)
@@ -281,7 +296,6 @@ static void __init legacy_pty_init(void)
        pty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW;
        pty_driver->other = pty_slave_driver;
        tty_set_operations(pty_driver, &pty_ops);
-       pty_driver->ioctl = pty_bsd_ioctl;
 
        pty_slave_driver->owner = THIS_MODULE;
        pty_slave_driver->driver_name = "pty_slave";
@@ -374,6 +388,19 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,
        return -ENOIOCTLCMD;
 }
 
+static const struct tty_operations pty_unix98_ops = {
+       .open = pty_open,
+       .close = pty_close,
+       .write = pty_write,
+       .write_room = pty_write_room,
+       .flush_buffer = pty_flush_buffer,
+       .chars_in_buffer = pty_chars_in_buffer,
+       .unthrottle = pty_unthrottle,
+       .set_termios = pty_set_termios,
+       .ioctl = pty_unix98_ioctl
+};
+
+
 static void __init unix98_pty_init(void)
 {
        ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
@@ -400,8 +427,7 @@ static void __init unix98_pty_init(void)
        ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW |
                TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM;
        ptm_driver->other = pts_driver;
-       tty_set_operations(ptm_driver, &pty_ops);
-       ptm_driver->ioctl = pty_unix98_ioctl;
+       tty_set_operations(ptm_driver, &pty_unix98_ops);
 
        pts_driver->owner = THIS_MODULE;
        pts_driver->driver_name = "pty_slave";
index f43c89f7c449831b2441f5f8f55441f2253a65ce..0cf98bd4f2d2438351357890a2cee00062b6c6da 100644 (file)
@@ -272,7 +272,7 @@ static int random_write_wakeup_thresh = 128;
 
 static int trickle_thresh __read_mostly = INPUT_POOL_WORDS * 28;
 
-static DEFINE_PER_CPU(int, trickle_count) = 0;
+static DEFINE_PER_CPU(int, trickle_count);
 
 /*
  * A pool of size .poolwords is stirred with a primitive polynomial
@@ -370,17 +370,19 @@ static struct poolinfo {
  */
 static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
 static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
+static struct fasync_struct *fasync;
 
 #if 0
-static int debug = 0;
+static int debug;
 module_param(debug, bool, 0644);
-#define DEBUG_ENT(fmt, arg...) do { if (debug) \
-       printk(KERN_DEBUG "random %04d %04d %04d: " \
-       fmt,\
-       input_pool.entropy_count,\
-       blocking_pool.entropy_count,\
-       nonblocking_pool.entropy_count,\
-       ## arg); } while (0)
+#define DEBUG_ENT(fmt, arg...) do { \
+       if (debug) \
+               printk(KERN_DEBUG "random %04d %04d %04d: " \
+               fmt,\
+               input_pool.entropy_count,\
+               blocking_pool.entropy_count,\
+               nonblocking_pool.entropy_count,\
+               ## arg); } while (0)
 #else
 #define DEBUG_ENT(fmt, arg...) do {} while (0)
 #endif
@@ -394,7 +396,7 @@ module_param(debug, bool, 0644);
 
 struct entropy_store;
 struct entropy_store {
-       /* mostly-read data: */
+       /* read-only data: */
        struct poolinfo *poolinfo;
        __u32 *pool;
        const char *name;
@@ -402,7 +404,7 @@ struct entropy_store {
        struct entropy_store *pull;
 
        /* read-write data: */
-       spinlock_t lock ____cacheline_aligned_in_smp;
+       spinlock_t lock;
        unsigned add_ptr;
        int entropy_count;
        int input_rotate;
@@ -438,25 +440,26 @@ static struct entropy_store nonblocking_pool = {
 };
 
 /*
- * This function adds a byte into the entropy "pool".  It does not
+ * This function adds bytes into the entropy "pool".  It does not
  * update the entropy estimate.  The caller should call
- * credit_entropy_store if this is appropriate.
+ * credit_entropy_bits if this is appropriate.
  *
  * The pool is stirred with a primitive polynomial of the appropriate
  * degree, and then twisted.  We twist by three bits at a time because
  * it's cheap to do so and helps slightly in the expected case where
  * the entropy is concentrated in the low-order bits.
  */
-static void __add_entropy_words(struct entropy_store *r, const __u32 *in,
-                               int nwords, __u32 out[16])
+static void mix_pool_bytes_extract(struct entropy_store *r, const void *in,
+                                  int nbytes, __u8 out[64])
 {
        static __u32 const twist_table[8] = {
                0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
                0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
-       unsigned long i, add_ptr, tap1, tap2, tap3, tap4, tap5;
-       int new_rotate, input_rotate;
+       unsigned long i, j, tap1, tap2, tap3, tap4, tap5;
+       int input_rotate;
        int wordmask = r->poolinfo->poolwords - 1;
-       __u32 w, next_w;
+       const char *bytes = in;
+       __u32 w;
        unsigned long flags;
 
        /* Taps are constant, so we can load them without holding r->lock.  */
@@ -465,78 +468,76 @@ static void __add_entropy_words(struct entropy_store *r, const __u32 *in,
        tap3 = r->poolinfo->tap3;
        tap4 = r->poolinfo->tap4;
        tap5 = r->poolinfo->tap5;
-       next_w = *in++;
 
        spin_lock_irqsave(&r->lock, flags);
-       prefetch_range(r->pool, wordmask);
        input_rotate = r->input_rotate;
-       add_ptr = r->add_ptr;
+       i = r->add_ptr;
 
-       while (nwords--) {
-               w = rol32(next_w, input_rotate);
-               if (nwords > 0)
-                       next_w = *in++;
-               i = add_ptr = (add_ptr - 1) & wordmask;
-               /*
-                * Normally, we add 7 bits of rotation to the pool.
-                * At the beginning of the pool, add an extra 7 bits
-                * rotation, so that successive passes spread the
-                * input bits across the pool evenly.
-                */
-               new_rotate = input_rotate + 14;
-               if (i)
-                       new_rotate = input_rotate + 7;
-               input_rotate = new_rotate & 31;
+       /* mix one byte at a time to simplify size handling and churn faster */
+       while (nbytes--) {
+               w = rol32(*bytes++, input_rotate & 31);
+               i = (i - 1) & wordmask;
 
                /* XOR in the various taps */
+               w ^= r->pool[i];
                w ^= r->pool[(i + tap1) & wordmask];
                w ^= r->pool[(i + tap2) & wordmask];
                w ^= r->pool[(i + tap3) & wordmask];
                w ^= r->pool[(i + tap4) & wordmask];
                w ^= r->pool[(i + tap5) & wordmask];
-               w ^= r->pool[i];
+
+               /* Mix the result back in with a twist */
                r->pool[i] = (w >> 3) ^ twist_table[w & 7];
+
+               /*
+                * Normally, we add 7 bits of rotation to the pool.
+                * At the beginning of the pool, add an extra 7 bits
+                * rotation, so that successive passes spread the
+                * input bits across the pool evenly.
+                */
+               input_rotate += i ? 7 : 14;
        }
 
        r->input_rotate = input_rotate;
-       r->add_ptr = add_ptr;
+       r->add_ptr = i;
 
-       if (out) {
-               for (i = 0; i < 16; i++) {
-                       out[i] = r->pool[add_ptr];
-                       add_ptr = (add_ptr - 1) & wordmask;
-               }
-       }
+       if (out)
+               for (j = 0; j < 16; j++)
+                       ((__u32 *)out)[j] = r->pool[(i - j) & wordmask];
 
        spin_unlock_irqrestore(&r->lock, flags);
 }
 
-static inline void add_entropy_words(struct entropy_store *r, const __u32 *in,
-                                    int nwords)
+static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes)
 {
-       __add_entropy_words(r, in, nwords, NULL);
+       mix_pool_bytes_extract(r, in, bytes, NULL);
 }
 
 /*
  * Credit (or debit) the entropy store with n bits of entropy
  */
-static void credit_entropy_store(struct entropy_store *r, int nbits)
+static void credit_entropy_bits(struct entropy_store *r, int nbits)
 {
        unsigned long flags;
 
+       if (!nbits)
+               return;
+
        spin_lock_irqsave(&r->lock, flags);
 
-       if (r->entropy_count + nbits < 0) {
-               DEBUG_ENT("negative entropy/overflow (%d+%d)\n",
-                         r->entropy_count, nbits);
+       DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name);
+       r->entropy_count += nbits;
+       if (r->entropy_count < 0) {
+               DEBUG_ENT("negative entropy/overflow\n");
                r->entropy_count = 0;
-       } else if (r->entropy_count + nbits > r->poolinfo->POOLBITS) {
+       } else if (r->entropy_count > r->poolinfo->POOLBITS)
                r->entropy_count = r->poolinfo->POOLBITS;
-       } else {
-               r->entropy_count += nbits;
-               if (nbits)
-                       DEBUG_ENT("added %d entropy credits to %s\n",
-                                 nbits, r->name);
+
+       /* should we wake readers? */
+       if (r == &input_pool &&
+           r->entropy_count >= random_read_wakeup_thresh) {
+               wake_up_interruptible(&random_read_wait);
+               kill_fasync(&fasync, SIGIO, POLL_IN);
        }
 
        spin_unlock_irqrestore(&r->lock, flags);
@@ -551,7 +552,7 @@ static void credit_entropy_store(struct entropy_store *r, int nbits)
 /* There is one of these per entropy source */
 struct timer_rand_state {
        cycles_t last_time;
-       long last_delta,last_delta2;
+       long last_delta, last_delta2;
        unsigned dont_count_entropy:1;
 };
 
@@ -586,7 +587,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
        sample.jiffies = jiffies;
        sample.cycles = get_cycles();
        sample.num = num;
-       add_entropy_words(&input_pool, (u32 *)&sample, sizeof(sample)/4);
+       mix_pool_bytes(&input_pool, &sample, sizeof(sample));
 
        /*
         * Calculate number of bits of randomness we probably added.
@@ -620,13 +621,9 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
                 * Round down by 1 bit on general principles,
                 * and limit entropy entimate to 12 bits.
                 */
-               credit_entropy_store(&input_pool,
-                                    min_t(int, fls(delta>>1), 11));
+               credit_entropy_bits(&input_pool,
+                                   min_t(int, fls(delta>>1), 11));
        }
-
-       if(input_pool.entropy_count >= random_read_wakeup_thresh)
-               wake_up_interruptible(&random_read_wait);
-
 out:
        preempt_enable();
 }
@@ -677,7 +674,7 @@ void add_disk_randomness(struct gendisk *disk)
  *
  *********************************************************************/
 
-static ssize_t extract_entropy(struct entropy_store *r, void * buf,
+static ssize_t extract_entropy(struct entropy_store *r, void *buf,
                               size_t nbytes, int min, int rsvd);
 
 /*
@@ -704,10 +701,10 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
                          "(%d of %d requested)\n",
                          r->name, bytes * 8, nbytes * 8, r->entropy_count);
 
-               bytes=extract_entropy(r->pull, tmp, bytes,
-                                     random_read_wakeup_thresh / 8, rsvd);
-               add_entropy_words(r, tmp, (bytes + 3) / 4);
-               credit_entropy_store(r, bytes*8);
+               bytes = extract_entropy(r->pull, tmp, bytes,
+                                       random_read_wakeup_thresh / 8, rsvd);
+               mix_pool_bytes(r, tmp, bytes);
+               credit_entropy_bits(r, bytes*8);
        }
 }
 
@@ -744,13 +741,15 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
                if (r->limit && nbytes + reserved >= r->entropy_count / 8)
                        nbytes = r->entropy_count/8 - reserved;
 
-               if(r->entropy_count / 8 >= nbytes + reserved)
+               if (r->entropy_count / 8 >= nbytes + reserved)
                        r->entropy_count -= nbytes*8;
                else
                        r->entropy_count = reserved;
 
-               if (r->entropy_count < random_write_wakeup_thresh)
+               if (r->entropy_count < random_write_wakeup_thresh) {
                        wake_up_interruptible(&random_write_wait);
+                       kill_fasync(&fasync, SIGIO, POLL_OUT);
+               }
        }
 
        DEBUG_ENT("debiting %d entropy credits from %s%s\n",
@@ -764,45 +763,46 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
 static void extract_buf(struct entropy_store *r, __u8 *out)
 {
        int i;
-       __u32 data[16], buf[5 + SHA_WORKSPACE_WORDS];
+       __u32 hash[5], workspace[SHA_WORKSPACE_WORDS];
+       __u8 extract[64];
+
+       /* Generate a hash across the pool, 16 words (512 bits) at a time */
+       sha_init(hash);
+       for (i = 0; i < r->poolinfo->poolwords; i += 16)
+               sha_transform(hash, (__u8 *)(r->pool + i), workspace);
 
-       sha_init(buf);
        /*
-        * As we hash the pool, we mix intermediate values of
-        * the hash back into the pool.  This eliminates
-        * backtracking attacks (where the attacker knows
-        * the state of the pool plus the current outputs, and
-        * attempts to find previous ouputs), unless the hash
-        * function can be inverted.
+        * We mix the hash back into the pool to prevent backtracking
+        * attacks (where the attacker knows the state of the pool
+        * plus the current outputs, and attempts to find previous
+        * ouputs), unless the hash function can be inverted. By
+        * mixing at least a SHA1 worth of hash data back, we make
+        * brute-forcing the feedback as hard as brute-forcing the
+        * hash.
         */
-       for (i = 0; i < r->poolinfo->poolwords; i += 16) {
-               /* hash blocks of 16 words = 512 bits */
-               sha_transform(buf, (__u8 *)(r->pool + i), buf + 5);
-               /* feed back portion of the resulting hash */
-               add_entropy_words(r, &buf[i % 5], 1);
-       }
+       mix_pool_bytes_extract(r, hash, sizeof(hash), extract);
 
        /*
-        * To avoid duplicates, we atomically extract a
-        * portion of the pool while mixing, and hash one
-        * final time.
+        * To avoid duplicates, we atomically extract a portion of the
+        * pool while mixing, and hash one final time.
         */
-       __add_entropy_words(r, &buf[i % 5], 1, data);
-       sha_transform(buf, (__u8 *)data, buf + 5);
+       sha_transform(hash, extract, workspace);
+       memset(extract, 0, sizeof(extract));
+       memset(workspace, 0, sizeof(workspace));
 
        /*
-        * In case the hash function has some recognizable
-        * output pattern, we fold it in half.
+        * In case the hash function has some recognizable output
+        * pattern, we fold it in half. Thus, we always feed back
+        * twice as much data as we output.
         */
-
-       buf[0] ^= buf[3];
-       buf[1] ^= buf[4];
-       buf[2] ^= rol32(buf[2], 16);
-       memcpy(out, buf, EXTRACT_SIZE);
-       memset(buf, 0, sizeof(buf));
+       hash[0] ^= hash[3];
+       hash[1] ^= hash[4];
+       hash[2] ^= rol32(hash[2], 16);
+       memcpy(out, hash, EXTRACT_SIZE);
+       memset(hash, 0, sizeof(hash));
 }
 
-static ssize_t extract_entropy(struct entropy_store *r, void * buf,
+static ssize_t extract_entropy(struct entropy_store *r, void *buf,
                               size_t nbytes, int min, int reserved)
 {
        ssize_t ret = 0, i;
@@ -872,7 +872,6 @@ void get_random_bytes(void *buf, int nbytes)
 {
        extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
 }
-
 EXPORT_SYMBOL(get_random_bytes);
 
 /*
@@ -894,12 +893,11 @@ static void init_std_data(struct entropy_store *r)
        spin_unlock_irqrestore(&r->lock, flags);
 
        now = ktime_get_real();
-       add_entropy_words(r, (__u32 *)&now, sizeof(now)/4);
-       add_entropy_words(r, (__u32 *)utsname(),
-                         sizeof(*(utsname()))/4);
+       mix_pool_bytes(r, &now, sizeof(now));
+       mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
 }
 
-static int __init rand_initialize(void)
+static int rand_initialize(void)
 {
        init_std_data(&input_pool);
        init_std_data(&blocking_pool);
@@ -940,7 +938,7 @@ void rand_initialize_disk(struct gendisk *disk)
 #endif
 
 static ssize_t
-random_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
+random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 {
        ssize_t n, retval = 0, count = 0;
 
@@ -1002,8 +1000,7 @@ random_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
 }
 
 static ssize_t
-urandom_read(struct file * file, char __user * buf,
-                     size_t nbytes, loff_t *ppos)
+urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 {
        return extract_entropy_user(&nonblocking_pool, buf, nbytes);
 }
@@ -1038,16 +1035,15 @@ write_pool(struct entropy_store *r, const char __user *buffer, size_t count)
                count -= bytes;
                p += bytes;
 
-               add_entropy_words(r, buf, (bytes + 3) / 4);
+               mix_pool_bytes(r, buf, bytes);
                cond_resched();
        }
 
        return 0;
 }
 
-static ssize_t
-random_write(struct file * file, const char __user * buffer,
-            size_t count, loff_t *ppos)
+static ssize_t random_write(struct file *file, const char __user *buffer,
+                           size_t count, loff_t *ppos)
 {
        size_t ret;
        struct inode *inode = file->f_path.dentry->d_inode;
@@ -1064,9 +1060,7 @@ random_write(struct file * file, const char __user * buffer,
        return (ssize_t)count;
 }
 
-static int
-random_ioctl(struct inode * inode, struct file * file,
-            unsigned int cmd, unsigned long arg)
+static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
 {
        int size, ent_count;
        int __user *p = (int __user *)arg;
@@ -1074,8 +1068,8 @@ random_ioctl(struct inode * inode, struct file * file,
 
        switch (cmd) {
        case RNDGETENTCNT:
-               ent_count = input_pool.entropy_count;
-               if (put_user(ent_count, p))
+               /* inherently racy, no point locking */
+               if (put_user(input_pool.entropy_count, p))
                        return -EFAULT;
                return 0;
        case RNDADDTOENTCNT:
@@ -1083,13 +1077,7 @@ random_ioctl(struct inode * inode, struct file * file,
                        return -EPERM;
                if (get_user(ent_count, p))
                        return -EFAULT;
-               credit_entropy_store(&input_pool, ent_count);
-               /*
-                * Wake up waiting processes if we have enough
-                * entropy.
-                */
-               if (input_pool.entropy_count >= random_read_wakeup_thresh)
-                       wake_up_interruptible(&random_read_wait);
+               credit_entropy_bits(&input_pool, ent_count);
                return 0;
        case RNDADDENTROPY:
                if (!capable(CAP_SYS_ADMIN))
@@ -1104,39 +1092,45 @@ random_ioctl(struct inode * inode, struct file * file,
                                    size);
                if (retval < 0)
                        return retval;
-               credit_entropy_store(&input_pool, ent_count);
-               /*
-                * Wake up waiting processes if we have enough
-                * entropy.
-                */
-               if (input_pool.entropy_count >= random_read_wakeup_thresh)
-                       wake_up_interruptible(&random_read_wait);
+               credit_entropy_bits(&input_pool, ent_count);
                return 0;
        case RNDZAPENTCNT:
        case RNDCLEARPOOL:
                /* Clear the entropy pool counters. */
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
-               init_std_data(&input_pool);
-               init_std_data(&blocking_pool);
-               init_std_data(&nonblocking_pool);
+               rand_initialize();
                return 0;
        default:
                return -EINVAL;
        }
 }
 
+static int random_fasync(int fd, struct file *filp, int on)
+{
+       return fasync_helper(fd, filp, on, &fasync);
+}
+
+static int random_release(struct inode *inode, struct file *filp)
+{
+       return fasync_helper(-1, filp, 0, &fasync);
+}
+
 const struct file_operations random_fops = {
        .read  = random_read,
        .write = random_write,
        .poll  = random_poll,
-       .ioctl = random_ioctl,
+       .unlocked_ioctl = random_ioctl,
+       .fasync = random_fasync,
+       .release = random_release,
 };
 
 const struct file_operations urandom_fops = {
        .read  = urandom_read,
        .write = random_write,
-       .ioctl = random_ioctl,
+       .unlocked_ioctl = random_ioctl,
+       .fasync = random_fasync,
+       .release = random_release,
 };
 
 /***************************************************************
@@ -1157,7 +1151,6 @@ void generate_random_uuid(unsigned char uuid_out[16])
        /* Set the UUID variant to DCE */
        uuid_out[8] = (uuid_out[8] & 0x3F) | 0x80;
 }
-
 EXPORT_SYMBOL(generate_random_uuid);
 
 /********************************************************************
@@ -1339,7 +1332,7 @@ ctl_table random_table[] = {
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 
-static __u32 twothirdsMD4Transform (__u32 const buf[4], __u32 const in[12])
+static __u32 twothirdsMD4Transform(__u32 const buf[4], __u32 const in[12])
 {
        __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
 
@@ -1487,8 +1480,8 @@ __u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr,
         */
 
        memcpy(hash, saddr, 16);
-       hash[4]=((__force u16)sport << 16) + (__force u16)dport;
-       memcpy(&hash[5],keyptr->secret,sizeof(__u32) * 7);
+       hash[4] = ((__force u16)sport << 16) + (__force u16)dport;
+       memcpy(&hash[5], keyptr->secret, sizeof(__u32) * 7);
 
        seq = twothirdsMD4Transform((const __u32 *)daddr, hash) & HASH_MASK;
        seq += keyptr->count;
@@ -1538,10 +1531,10 @@ __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
         *  Note that the words are placed into the starting vector, which is
         *  then mixed with a partial MD4 over random data.
         */
-       hash[0]=(__force u32)saddr;
-       hash[1]=(__force u32)daddr;
-       hash[2]=((__force u16)sport << 16) + (__force u16)dport;
-       hash[3]=keyptr->secret[11];
+       hash[0] = (__force u32)saddr;
+       hash[1] = (__force u32)daddr;
+       hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
+       hash[3] = keyptr->secret[11];
 
        seq = half_md4_transform(hash, keyptr->secret) & HASH_MASK;
        seq += keyptr->count;
@@ -1556,10 +1549,7 @@ __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
         *      Choosing a clock of 64 ns period is OK. (period of 274 s)
         */
        seq += ktime_to_ns(ktime_get_real()) >> 6;
-#if 0
-       printk("init_seq(%lx, %lx, %d, %d) = %d\n",
-              saddr, daddr, sport, dport, seq);
-#endif
+
        return seq;
 }
 
@@ -1582,14 +1572,15 @@ u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
 }
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, __be16 dport)
+u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
+                              __be16 dport)
 {
        struct keydata *keyptr = get_keyptr();
        u32 hash[12];
 
        memcpy(hash, saddr, 16);
        hash[4] = (__force u32)dport;
-       memcpy(&hash[5],keyptr->secret,sizeof(__u32) * 7);
+       memcpy(&hash[5], keyptr->secret, sizeof(__u32) * 7);
 
        return twothirdsMD4Transform((const __u32 *)daddr, hash);
 }
@@ -1617,13 +1608,9 @@ u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
 
        seq += ktime_to_ns(ktime_get_real());
        seq &= (1ull << 48) - 1;
-#if 0
-       printk("dccp init_seq(%lx, %lx, %d, %d) = %d\n",
-              saddr, daddr, sport, dport, seq);
-#endif
+
        return seq;
 }
-
 EXPORT_SYMBOL(secure_dccp_sequence_number);
 #endif
 
index f4f837f868290a5e4baebfd61ae04e9b7f366c20..a03a538a3efb0d59eb0a5b0c1e47711ff3852433 100644 (file)
 /* Bit fields for particular registers shared with driver */
 
 /* COR1 - driver and RTA */
-#define        COR1_ODD        0x80    /* Odd parity */
-#define COR1_EVEN      0x00    /* Even parity */
-#define        COR1_NOP        0x00    /* No parity */
-#define        COR1_FORCE      0x20    /* Force parity */
-#define        COR1_NORMAL     0x40    /* With parity */
-#define        COR1_1STOP      0x00    /* 1 stop bit */
-#define        COR1_15STOP     0x04    /* 1.5 stop bits */
-#define        COR1_2STOP      0x08    /* 2 stop bits */
-#define        COR1_5BITS      0x00    /* 5 data bits */
-#define        COR1_6BITS      0x01    /* 6 data bits */
-#define        COR1_7BITS      0x02    /* 7 data bits */
-#define        COR1_8BITS      0x03    /* 8 data bits */
-
-#define COR1_HOST       0xef   /* Safe host bits */
+#define RIOC_COR1_ODD          0x80    /* Odd parity */
+#define RIOC_COR1_EVEN         0x00    /* Even parity */
+#define RIOC_COR1_NOP          0x00    /* No parity */
+#define RIOC_COR1_FORCE                0x20    /* Force parity */
+#define RIOC_COR1_NORMAL       0x40    /* With parity */
+#define RIOC_COR1_1STOP                0x00    /* 1 stop bit */
+#define RIOC_COR1_15STOP       0x04    /* 1.5 stop bits */
+#define RIOC_COR1_2STOP                0x08    /* 2 stop bits */
+#define RIOC_COR1_5BITS                0x00    /* 5 data bits */
+#define RIOC_COR1_6BITS                0x01    /* 6 data bits */
+#define RIOC_COR1_7BITS                0x02    /* 7 data bits */
+#define RIOC_COR1_8BITS                0x03    /* 8 data bits */
+
+#define RIOC_COR1_HOST         0xef    /* Safe host bits */
 
 /* RTA only */
-#define COR1_CINPCK     0x00   /* Check parity of received characters */
-#define COR1_CNINPCK    0x10   /* Don't check parity */
+#define RIOC_COR1_CINPCK       0x00    /* Check parity of received characters */
+#define RIOC_COR1_CNINPCK      0x10    /* Don't check parity */
 
 /* COR2 bits for both RTA and driver use */
-#define        COR2_IXANY      0x80    /* IXANY - any character is XON */
-#define        COR2_IXON       0x40    /* IXON - enable tx soft flowcontrol */
-#define        COR2_RTSFLOW    0x02    /* Enable tx hardware flow control */
+#define RIOC_COR2_IXANY                0x80    /* IXANY - any character is XON */
+#define RIOC_COR2_IXON         0x40    /* IXON - enable tx soft flowcontrol */
+#define RIOC_COR2_RTSFLOW      0x02    /* Enable tx hardware flow control */
 
 /* Additional driver bits */
-#define        COR2_HUPCL      0x20    /* Hang up on close */
-#define        COR2_CTSFLOW    0x04    /* Enable rx hardware flow control */
-#define        COR2_IXOFF      0x01    /* Enable rx software flow control */
-#define COR2_DTRFLOW   0x08    /* Enable tx hardware flow control */
+#define RIOC_COR2_HUPCL                0x20    /* Hang up on close */
+#define RIOC_COR2_CTSFLOW      0x04    /* Enable rx hardware flow control */
+#define RIOC_COR2_IXOFF                0x01    /* Enable rx software flow control */
+#define RIOC_COR2_DTRFLOW      0x08    /* Enable tx hardware flow control */
 
 /* RTA use only */
-#define COR2_ETC       0x20    /* Embedded transmit options */
-#define        COR2_LOCAL      0x10    /* Local loopback mode */
-#define        COR2_REMOTE     0x08    /* Remote loopback mode */
-#define        COR2_HOST       0xc2    /* Safe host bits */
+#define RIOC_COR2_ETC          0x20    /* Embedded transmit options */
+#define RIOC_COR2_LOCAL                0x10    /* Local loopback mode */
+#define RIOC_COR2_REMOTE       0x08    /* Remote loopback mode */
+#define RIOC_COR2_HOST         0xc2    /* Safe host bits */
 
 /* COR3 - RTA use only */
-#define        COR3_SCDRNG     0x80    /* Enable special char detect for range */
-#define        COR3_SCD34      0x40    /* Special character detect for SCHR's 3 + 4 */
-#define        COR3_FCT        0x20    /* Flow control transparency */
-#define        COR3_SCD12      0x10    /* Special character detect for SCHR's 1 + 2 */
-#define        COR3_FIFO12     0x0c    /* 12 chars for receive FIFO threshold */
-#define COR3_FIFO10     0x0a   /* 10 chars for receive FIFO threshold */
-#define COR3_FIFO8      0x08   /* 8 chars for receive FIFO threshold */
-#define COR3_FIFO6      0x06   /* 6 chars for receive FIFO threshold */
-
-#define COR3_THRESHOLD  COR3_FIFO8     /* MUST BE LESS THAN MCOR_THRESHOLD */
-
-#define        COR3_DEFAULT    (COR3_FCT | COR3_THRESHOLD)
+#define RIOC_COR3_SCDRNG       0x80    /* Enable special char detect for range */
+#define RIOC_COR3_SCD34                0x40    /* Special character detect for SCHR's 3 + 4 */
+#define RIOC_COR3_FCT          0x20    /* Flow control transparency */
+#define RIOC_COR3_SCD12                0x10    /* Special character detect for SCHR's 1 + 2 */
+#define RIOC_COR3_FIFO12       0x0c    /* 12 chars for receive FIFO threshold */
+#define RIOC_COR3_FIFO10       0x0a    /* 10 chars for receive FIFO threshold */
+#define RIOC_COR3_FIFO8                0x08    /* 8 chars for receive FIFO threshold */
+#define RIOC_COR3_FIFO6                0x06    /* 6 chars for receive FIFO threshold */
+
+#define RIOC_COR3_THRESHOLD    RIOC_COR3_FIFO8 /* MUST BE LESS THAN MCOR_THRESHOLD */
+
+#define RIOC_COR3_DEFAULT      (RIOC_COR3_FCT | RIOC_COR3_THRESHOLD)
                                /* Default bits for COR3 */
 
 /* COR4 driver and RTA use */
-#define        COR4_IGNCR      0x80    /* Throw away CR's on input */
-#define        COR4_ICRNL      0x40    /* Map CR -> NL on input */
-#define        COR4_INLCR      0x20    /* Map NL -> CR on input */
-#define        COR4_IGNBRK     0x10    /* Ignore Break */
-#define        COR4_NBRKINT    0x08    /* No interrupt on break (-BRKINT) */
-#define COR4_RAISEMOD  0x01    /* Raise modem output lines on non-zero baud */
+#define RIOC_COR4_IGNCR                0x80    /* Throw away CR's on input */
+#define RIOC_COR4_ICRNL                0x40    /* Map CR -> NL on input */
+#define RIOC_COR4_INLCR                0x20    /* Map NL -> CR on input */
+#define RIOC_COR4_IGNBRK       0x10    /* Ignore Break */
+#define RIOC_COR4_NBRKINT      0x08    /* No interrupt on break (-BRKINT) */
+#define RIOC_COR4_RAISEMOD     0x01    /* Raise modem output lines on non-zero baud */
 
 
 /* COR4 driver only */
-#define COR4_IGNPAR    0x04    /* IGNPAR (ignore characters with errors) */
-#define COR4_PARMRK    0x02    /* PARMRK */
+#define RIOC_COR4_IGNPAR       0x04    /* IGNPAR (ignore characters with errors) */
+#define RIOC_COR4_PARMRK       0x02    /* PARMRK */
 
-#define COR4_HOST      0xf8    /* Safe host bits */
+#define RIOC_COR4_HOST         0xf8    /* Safe host bits */
 
 /* COR4 RTA only */
-#define COR4_CIGNPAR   0x02    /* Thrown away bad characters */
-#define COR4_CPARMRK   0x04    /* PARMRK characters */
-#define COR4_CNPARMRK  0x03    /* Don't PARMRK */
+#define RIOC_COR4_CIGNPAR      0x02    /* Thrown away bad characters */
+#define RIOC_COR4_CPARMRK      0x04    /* PARMRK characters */
+#define RIOC_COR4_CNPARMRK     0x03    /* Don't PARMRK */
 
 /* COR5 driver and RTA use */
-#define        COR5_ISTRIP     0x80    /* Strip input chars to 7 bits */
-#define        COR5_LNE        0x40    /* Enable LNEXT processing */
-#define        COR5_CMOE       0x20    /* Match good and errored characters */
-#define        COR5_ONLCR      0x02    /* NL -> CR NL on output */
-#define        COR5_OCRNL      0x01    /* CR -> NL on output */
+#define RIOC_COR5_ISTRIP       0x80    /* Strip input chars to 7 bits */
+#define RIOC_COR5_LNE          0x40    /* Enable LNEXT processing */
+#define RIOC_COR5_CMOE         0x20    /* Match good and errored characters */
+#define RIOC_COR5_ONLCR                0x02    /* NL -> CR NL on output */
+#define RIOC_COR5_OCRNL                0x01    /* CR -> NL on output */
 
 /*
 ** Spare bits - these are not used in the CIRRUS registers, so we use
 /*
 ** tstop and tbusy indication
 */
-#define        COR5_TSTATE_ON  0x08    /* Turn on monitoring of tbusy and tstop */
-#define        COR5_TSTATE_OFF 0x04    /* Turn off monitoring of tbusy and tstop */
+#define RIOC_COR5_TSTATE_ON    0x08    /* Turn on monitoring of tbusy and tstop */
+#define RIOC_COR5_TSTATE_OFF   0x04    /* Turn off monitoring of tbusy and tstop */
 /*
 ** TAB3
 */
-#define        COR5_TAB3       0x10    /* TAB3 mode */
+#define RIOC_COR5_TAB3         0x10    /* TAB3 mode */
 
-#define        COR5_HOST       0xc3    /* Safe host bits */
+#define RIOC_COR5_HOST         0xc3    /* Safe host bits */
 
 /* CCSR */
-#define        CCSR_TXFLOFF    0x04    /* Tx is xoffed */
+#define RIOC_CCSR_TXFLOFF      0x04    /* Tx is xoffed */
 
 /* MSVR1 */
 /* NB. DTR / CD swapped from Cirrus spec as the pins are also reversed on the
    RTA. This is because otherwise DCD would get lost on the 1 parallel / 3
    serial option.
 */
-#define        MSVR1_CD        0x80    /* CD (DSR on Cirrus) */
-#define        MSVR1_RTS       0x40    /* RTS (CTS on Cirrus) */
-#define        MSVR1_RI        0x20    /* RI */
-#define        MSVR1_DTR       0x10    /* DTR (CD on Cirrus) */
-#define        MSVR1_CTS       0x01    /* CTS output pin (RTS on Cirrus) */
+#define RIOC_MSVR1_CD          0x80    /* CD (DSR on Cirrus) */
+#define RIOC_MSVR1_RTS         0x40    /* RTS (CTS on Cirrus) */
+#define RIOC_MSVR1_RI          0x20    /* RI */
+#define RIOC_MSVR1_DTR         0x10    /* DTR (CD on Cirrus) */
+#define RIOC_MSVR1_CTS         0x01    /* CTS output pin (RTS on Cirrus) */
 /* Next two used to indicate state of tbusy and tstop to driver */
-#define        MSVR1_TSTOP     0x08    /* Set if port flow controlled */
-#define        MSVR1_TEMPTY    0x04    /* Set if port tx buffer empty */
+#define RIOC_MSVR1_TSTOP       0x08    /* Set if port flow controlled */
+#define RIOC_MSVR1_TEMPTY      0x04    /* Set if port tx buffer empty */
 
-#define        MSVR1_HOST      0xf3    /* The bits the host wants */
+#define RIOC_MSVR1_HOST                0xf3    /* The bits the host wants */
 
 /* Defines for the subscripts of a CONFIG packet */
-#define        CONFIG_COR1     1       /* Option register 1 */
-#define        CONFIG_COR2     2       /* Option register 2 */
-#define        CONFIG_COR4     3       /* Option register 4 */
-#define        CONFIG_COR5     4       /* Option register 5 */
-#define        CONFIG_TXXON    5       /* Tx XON character */
-#define        CONFIG_TXXOFF   6       /* Tx XOFF character */
-#define        CONFIG_RXXON    7       /* Rx XON character */
-#define        CONFIG_RXXOFF   8       /* Rx XOFF character */
-#define CONFIG_LNEXT   9       /* LNEXT character */
-#define        CONFIG_TXBAUD   10      /* Tx baud rate */
-#define        CONFIG_RXBAUD   11      /* Rx baud rate */
-
-#define        PRE_EMPTIVE     0x80    /* Pre-emptive bit in command field */
+#define RIOC_CONFIG_COR1       1       /* Option register 1 */
+#define RIOC_CONFIG_COR2       2       /* Option register 2 */
+#define RIOC_CONFIG_COR4       3       /* Option register 4 */
+#define RIOC_CONFIG_COR5       4       /* Option register 5 */
+#define RIOC_CONFIG_TXXON      5       /* Tx XON character */
+#define RIOC_CONFIG_TXXOFF     6       /* Tx XOFF character */
+#define RIOC_CONFIG_RXXON      7       /* Rx XON character */
+#define RIOC_CONFIG_RXXOFF     8       /* Rx XOFF character */
+#define RIOC_CONFIG_LNEXT      9       /* LNEXT character */
+#define RIOC_CONFIG_TXBAUD     10      /* Tx baud rate */
+#define RIOC_CONFIG_RXBAUD     11      /* Rx baud rate */
+
+#define RIOC_PRE_EMPTIVE       0x80    /* Pre-emptive bit in command field */
 
 /* Packet types going from Host to remote - with the exception of OPEN, MOPEN,
    CONFIG, SBREAK and MEMDUMP the remaining bytes of the data array will not
    be used 
 */
-#define        OPEN            0x00    /* Open a port */
-#define CONFIG         0x01    /* Configure a port */
-#define        MOPEN           0x02    /* Modem open (block for DCD) */
-#define        CLOSE           0x03    /* Close a port */
-#define        WFLUSH          (0x04 | PRE_EMPTIVE)    /* Write flush */
-#define        RFLUSH          (0x05 | PRE_EMPTIVE)    /* Read flush */
-#define        RESUME          (0x06 | PRE_EMPTIVE)    /* Resume if xoffed */
-#define        SBREAK          0x07    /* Start break */
-#define        EBREAK          0x08    /* End break */
-#define        SUSPEND         (0x09 | PRE_EMPTIVE)    /* Susp op (behave as tho xoffed) */
-#define FCLOSE          (0x0a | PRE_EMPTIVE)   /* Force close */
-#define XPRINT          0x0b   /* Xprint packet */
-#define MBIS           (0x0c | PRE_EMPTIVE)    /* Set modem lines */
-#define MBIC           (0x0d | PRE_EMPTIVE)    /* Clear modem lines */
-#define MSET           (0x0e | PRE_EMPTIVE)    /* Set modem lines */
-#define PCLOSE         0x0f    /* Pseudo close - Leaves rx/tx enabled */
-#define MGET           (0x10 | PRE_EMPTIVE)    /* Force update of modem status */
-#define MEMDUMP                (0x11 | PRE_EMPTIVE)    /* Send back mem from addr supplied */
-#define        READ_REGISTER   (0x12 | PRE_EMPTIVE)    /* Read CD1400 register (debug) */
+#define RIOC_OPEN              0x00    /* Open a port */
+#define RIOC_CONFIG            0x01    /* Configure a port */
+#define RIOC_MOPEN             0x02    /* Modem open (block for DCD) */
+#define RIOC_CLOSE             0x03    /* Close a port */
+#define RIOC_WFLUSH            (0x04 | RIOC_PRE_EMPTIVE)       /* Write flush */
+#define RIOC_RFLUSH            (0x05 | RIOC_PRE_EMPTIVE)       /* Read flush */
+#define RIOC_RESUME            (0x06 | RIOC_PRE_EMPTIVE)       /* Resume if xoffed */
+#define RIOC_SBREAK            0x07    /* Start break */
+#define RIOC_EBREAK            0x08    /* End break */
+#define RIOC_SUSPEND           (0x09 | RIOC_PRE_EMPTIVE)       /* Susp op (behave as tho xoffed) */
+#define RIOC_FCLOSE            (0x0a | RIOC_PRE_EMPTIVE)       /* Force close */
+#define RIOC_XPRINT            0x0b    /* Xprint packet */
+#define RIOC_MBIS              (0x0c | RIOC_PRE_EMPTIVE)       /* Set modem lines */
+#define RIOC_MBIC              (0x0d | RIOC_PRE_EMPTIVE)       /* Clear modem lines */
+#define RIOC_MSET              (0x0e | RIOC_PRE_EMPTIVE)       /* Set modem lines */
+#define RIOC_PCLOSE            0x0f    /* Pseudo close - Leaves rx/tx enabled */
+#define RIOC_MGET              (0x10 | RIOC_PRE_EMPTIVE)       /* Force update of modem status */
+#define RIOC_MEMDUMP           (0x11 | RIOC_PRE_EMPTIVE)       /* Send back mem from addr supplied */
+#define RIOC_READ_REGISTER     (0x12 | RIOC_PRE_EMPTIVE)       /* Read CD1400 register (debug) */
 
 /* "Command" packets going from remote to host COMPLETE and MODEM_STATUS
    use data[4] / data[3] to indicate current state and modem status respectively
 */
 
-#define        COMPLETE        (0x20 | PRE_EMPTIVE)
+#define RIOC_COMPLETE          (0x20 | RIOC_PRE_EMPTIVE)
                                /* Command complete */
-#define BREAK_RECEIVED (0x21 | PRE_EMPTIVE)
+#define RIOC_BREAK_RECEIVED    (0x21 | RIOC_PRE_EMPTIVE)
                                /* Break received */
-#define MODEM_STATUS   (0x22 | PRE_EMPTIVE)
+#define RIOC_MODEM_STATUS      (0x22 | RIOC_PRE_EMPTIVE)
                                /* Change in modem status */
 
 /* "Command" packet that could go either way - handshake wake-up */
-#define HANDSHAKE      (0x23 | PRE_EMPTIVE)
+#define RIOC_HANDSHAKE         (0x23 | RIOC_PRE_EMPTIVE)
                                /* Wake-up to HOST / RTA */
 
 #endif
index 0ce96670f97994093fdc39ed84af0c5efc69d024..412777cd1e6879f14e8edabff5e780897c9748e8 100644 (file)
@@ -344,7 +344,7 @@ int rio_minor(struct tty_struct *tty)
 
 static int rio_set_real_termios(void *ptr)
 {
-       return RIOParam((struct Port *) ptr, CONFIG, 1, 1);
+       return RIOParam((struct Port *) ptr, RIOC_CONFIG, 1, 1);
 }
 
 
@@ -487,7 +487,7 @@ static int rio_get_CD(void *ptr)
        int rv;
 
        func_enter();
-       rv = (PortP->ModemState & MSVR1_CD) != 0;
+       rv = (PortP->ModemState & RIOC_MSVR1_CD) != 0;
 
        rio_dprintk(RIO_DEBUG_INIT, "Getting CD status: %d\n", rv);
 
@@ -607,7 +607,8 @@ static int rio_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd
                        rio_dprintk(RIO_DEBUG_TTY, "BREAK on deleted RTA\n");
                        rc = -EIO;
                } else {
-                       if (RIOShortCommand(p, PortP, SBREAK, 2, 250) == RIO_FAIL) {
+                       if (RIOShortCommand(p, PortP, RIOC_SBREAK, 2, 250) ==
+                                       RIO_FAIL) {
                                rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
                                rc = -EIO;
                        }
@@ -622,7 +623,8 @@ static int rio_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd
                        l = arg ? arg * 100 : 250;
                        if (l > 255)
                                l = 255;
-                       if (RIOShortCommand(p, PortP, SBREAK, 2, arg ? arg * 100 : 250) == RIO_FAIL) {
+                       if (RIOShortCommand(p, PortP, RIOC_SBREAK, 2,
+                                       arg ? arg * 100 : 250) == RIO_FAIL) {
                                rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
                                rc = -EIO;
                        }
index dc3f005614a36d5cefbc9df333a1fa09aab8546a..7f26cd7c815e579d228fab9c290a5c8b4e525b52 100644 (file)
@@ -186,9 +186,9 @@ static inline void *rio_memcpy_fromio(void *dest, void __iomem *source, int n)
 
 #ifdef DEBUG
 #define rio_dprintk(f, str...) do { if (rio_debug & f) printk (str);} while (0)
-#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s\n", __FUNCTION__)
-#define func_exit()  rio_dprintk (RIO_DEBUG_FLOW, "rio: exit  %s\n", __FUNCTION__)
-#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s (port %d)\n",__FUNCTION__, port->line)
+#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s\n", __func__)
+#define func_exit()  rio_dprintk (RIO_DEBUG_FLOW, "rio: exit  %s\n", __func__)
+#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s (port %d)\n",__func__, port->line)
 #else
 #define rio_dprintk(f, str...) /* nothing */
 #define func_enter()
index bf36959fc12149edc7610c1bf4957fa52c08eda6..7b96e0814887d8f14ea5a1b793686acbc3b099b1 100644 (file)
@@ -417,7 +417,7 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struc
        PortP = p->RIOPortp[SysPort];
        rio_spin_lock_irqsave(&PortP->portSem, flags);
        switch (readb(&PktCmdP->Command)) {
-       case BREAK_RECEIVED:
+       case RIOC_BREAK_RECEIVED:
                rio_dprintk(RIO_DEBUG_CMD, "Received a break!\n");
                /* If the current line disc. is not multi-threading and
                   the current processor is not the default, reset rup_intr
@@ -428,16 +428,16 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struc
                gs_got_break(&PortP->gs);
                break;
 
-       case COMPLETE:
+       case RIOC_COMPLETE:
                rio_dprintk(RIO_DEBUG_CMD, "Command complete on phb %d host %Zd\n", readb(&PktCmdP->PhbNum), HostP - p->RIOHosts);
                subCommand = 1;
                switch (readb(&PktCmdP->SubCommand)) {
-               case MEMDUMP:
+               case RIOC_MEMDUMP:
                        rio_dprintk(RIO_DEBUG_CMD, "Memory dump cmd (0x%x) from addr 0x%x\n", readb(&PktCmdP->SubCommand), readw(&PktCmdP->SubAddr));
                        break;
-               case READ_REGISTER:
+               case RIOC_READ_REGISTER:
                        rio_dprintk(RIO_DEBUG_CMD, "Read register (0x%x)\n", readw(&PktCmdP->SubAddr));
-                       p->CdRegister = (readb(&PktCmdP->ModemStatus) & MSVR1_HOST);
+                       p->CdRegister = (readb(&PktCmdP->ModemStatus) & RIOC_MSVR1_HOST);
                        break;
                default:
                        subCommand = 0;
@@ -456,14 +456,15 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struc
                        rio_dprintk(RIO_DEBUG_CMD, "No change\n");
 
                /* FALLTHROUGH */
-       case MODEM_STATUS:
+       case RIOC_MODEM_STATUS:
                /*
                 ** Knock out the tbusy and tstop bits, as these are not relevant
                 ** to the check for modem status change (they're just there because
                 ** it's a convenient place to put them!).
                 */
                ReportedModemStatus = readb(&PktCmdP->ModemStatus);
-               if ((PortP->ModemState & MSVR1_HOST) == (ReportedModemStatus & MSVR1_HOST)) {
+               if ((PortP->ModemState & RIOC_MSVR1_HOST) ==
+                               (ReportedModemStatus & RIOC_MSVR1_HOST)) {
                        rio_dprintk(RIO_DEBUG_CMD, "Modem status unchanged 0x%x\n", PortP->ModemState);
                        /*
                         ** Update ModemState just in case tbusy or tstop states have
@@ -497,7 +498,7 @@ static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struc
                                        /*
                                         ** Is there a carrier?
                                         */
-                                       if (PortP->ModemState & MSVR1_CD) {
+                                       if (PortP->ModemState & RIOC_MSVR1_CD) {
                                                /*
                                                 ** Has carrier just appeared?
                                                 */
@@ -691,7 +692,7 @@ void RIOPollHostCommands(struct rio_info *p, struct Host *HostP)
                                 */
                                rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
                                FreeMe = RIOCommandRup(p, Rup, HostP, PacketP);
-                               if (readb(&PacketP->data[5]) == MEMDUMP) {
+                               if (readb(&PacketP->data[5]) == RIOC_MEMDUMP) {
                                        rio_dprintk(RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", readw(&(PacketP->data[6])));
                                        rio_memcpy_fromio(p->RIOMemDump, &(PacketP->data[8]), 32);
                                }
index d8eb2bcbe015dca54fce742555ec18142cb7851c..d65ceb9a434a49191cc84fa70355aab5fd964397 100644 (file)
@@ -422,7 +422,8 @@ int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su
                }
 
                rio_spin_lock_irqsave(&PortP->portSem, flags);
-               if (RIOPreemptiveCmd(p, (p->RIOPortp[port]), RESUME) == RIO_FAIL) {
+               if (RIOPreemptiveCmd(p, (p->RIOPortp[port]), RIOC_RESUME) ==
+                               RIO_FAIL) {
                        rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME failed\n");
                        rio_spin_unlock_irqrestore(&PortP->portSem, flags);
                        return -EBUSY;
@@ -636,7 +637,8 @@ int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su
                        return -ENXIO;
                }
                PortP = (p->RIOPortp[PortTty.port]);
-               RIOParam(PortP, CONFIG, PortP->State & RIO_MODEM, OK_TO_SLEEP);
+               RIOParam(PortP, RIOC_CONFIG, PortP->State & RIO_MODEM,
+                               OK_TO_SLEEP);
                return retval;
 
        case RIO_SET_PORT_PARAMS:
@@ -1247,7 +1249,7 @@ int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su
 
                rio_spin_lock_irqsave(&PortP->portSem, flags);
 
-               if (RIOPreemptiveCmd(p, PortP, MEMDUMP) == RIO_FAIL) {
+               if (RIOPreemptiveCmd(p, PortP, RIOC_MEMDUMP) == RIO_FAIL) {
                        rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP failed\n");
                        rio_spin_unlock_irqrestore(&PortP->portSem, flags);
                        return -EBUSY;
@@ -1313,7 +1315,8 @@ int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su
 
                rio_spin_lock_irqsave(&PortP->portSem, flags);
 
-               if (RIOPreemptiveCmd(p, PortP, READ_REGISTER) == RIO_FAIL) {
+               if (RIOPreemptiveCmd(p, PortP, RIOC_READ_REGISTER) ==
+                               RIO_FAIL) {
                        rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER failed\n");
                        rio_spin_unlock_irqrestore(&PortP->portSem, flags);
                        return -EBUSY;
@@ -1434,50 +1437,50 @@ int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd)
        PktCmdP->PhbNum = port;
 
        switch (Cmd) {
-       case MEMDUMP:
+       case RIOC_MEMDUMP:
                rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk %p "
                                "(addr 0x%x)\n", CmdBlkP, (int) SubCmd.Addr);
-               PktCmdP->SubCommand = MEMDUMP;
+               PktCmdP->SubCommand = RIOC_MEMDUMP;
                PktCmdP->SubAddr = SubCmd.Addr;
                break;
-       case FCLOSE:
+       case RIOC_FCLOSE:
                rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk %p\n",
                                CmdBlkP);
                break;
-       case READ_REGISTER:
+       case RIOC_READ_REGISTER:
                rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) "
                                "command blk %p\n", (int) SubCmd.Addr, CmdBlkP);
-               PktCmdP->SubCommand = READ_REGISTER;
+               PktCmdP->SubCommand = RIOC_READ_REGISTER;
                PktCmdP->SubAddr = SubCmd.Addr;
                break;
-       case RESUME:
+       case RIOC_RESUME:
                rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk %p\n",
                                CmdBlkP);
                break;
-       case RFLUSH:
+       case RIOC_RFLUSH:
                rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk %p\n",
                                CmdBlkP);
                CmdBlkP->PostFuncP = RIORFlushEnable;
                break;
-       case SUSPEND:
+       case RIOC_SUSPEND:
                rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk %p\n",
                                CmdBlkP);
                break;
 
-       case MGET:
+       case RIOC_MGET:
                rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk %p\n",
                                CmdBlkP);
                break;
 
-       case MSET:
-       case MBIC:
-       case MBIS:
+       case RIOC_MSET:
+       case RIOC_MBIC:
+       case RIOC_MBIS:
                CmdBlkP->Packet.data[4] = (char) PortP->ModemLines;
                rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command "
                                "blk %p\n", CmdBlkP);
                break;
 
-       case WFLUSH:
+       case RIOC_WFLUSH:
                /*
                 ** If we have queued up the maximum number of Write flushes
                 ** allowed then we should not bother sending any more to the
index 4734e26e1ccd8a694ba23e090e56b35fe890598c..ea21686c69a43293b41664546b134932e3837ca9 100644 (file)
@@ -401,9 +401,8 @@ void RIOServiceHost(struct rio_info *p, struct Host *HostP)
                                        PortP->InUse = NOT_INUSE;
 
                                        rio_spin_unlock(&PortP->portSem);
-                                       if (RIOParam(PortP, OPEN, ((PortP->Cor2Copy & (COR2_RTSFLOW | COR2_CTSFLOW)) == (COR2_RTSFLOW | COR2_CTSFLOW)) ? 1 : 0, DONT_SLEEP) == RIO_FAIL) {
+                                       if (RIOParam(PortP, RIOC_OPEN, ((PortP->Cor2Copy & (RIOC_COR2_RTSFLOW | RIOC_COR2_CTSFLOW)) == (RIOC_COR2_RTSFLOW | RIOC_COR2_CTSFLOW)) ? 1 : 0, DONT_SLEEP) == RIO_FAIL)
                                                continue;       /* with next port */
-                                       }
                                        rio_spin_lock(&PortP->portSem);
                                        PortP->MagicFlags &= ~MAGIC_REBOOT;
                                }
@@ -429,7 +428,7 @@ void RIOServiceHost(struct rio_info *p, struct Host *HostP)
                                         */
                                        PktCmdP = (struct PktCmd __iomem *) &PacketP->data[0];
 
-                                       writeb(WFLUSH, &PktCmdP->Command);
+                                       writeb(RIOC_WFLUSH, &PktCmdP->Command);
 
                                        p = PortP->HostPort % (u16) PORTS_PER_RTA;
 
index da276ed57b3f5b8ade87dc12f3188bd50404978c..4810b845cc21074f49fc72aba3c0e7aa5637bee6 100644 (file)
@@ -177,7 +177,7 @@ int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag)
        }
        rio_spin_lock_irqsave(&PortP->portSem, flags);
 
-       if (cmd == OPEN) {
+       if (cmd == RIOC_OPEN) {
                /*
                 ** If the port is set to store or lock the parameters, and it is
                 ** paramed with OPEN, we want to restore the saved port termio, but
@@ -241,50 +241,50 @@ int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag)
        case CS5:
                {
                        rio_dprintk(RIO_DEBUG_PARAM, "5 bit data\n");
-                       Cor1 |= COR1_5BITS;
+                       Cor1 |= RIOC_COR1_5BITS;
                        break;
                }
        case CS6:
                {
                        rio_dprintk(RIO_DEBUG_PARAM, "6 bit data\n");
-                       Cor1 |= COR1_6BITS;
+                       Cor1 |= RIOC_COR1_6BITS;
                        break;
                }
        case CS7:
                {
                        rio_dprintk(RIO_DEBUG_PARAM, "7 bit data\n");
-                       Cor1 |= COR1_7BITS;
+                       Cor1 |= RIOC_COR1_7BITS;
                        break;
                }
        case CS8:
                {
                        rio_dprintk(RIO_DEBUG_PARAM, "8 bit data\n");
-                       Cor1 |= COR1_8BITS;
+                       Cor1 |= RIOC_COR1_8BITS;
                        break;
                }
        }
 
        if (TtyP->termios->c_cflag & CSTOPB) {
                rio_dprintk(RIO_DEBUG_PARAM, "2 stop bits\n");
-               Cor1 |= COR1_2STOP;
+               Cor1 |= RIOC_COR1_2STOP;
        } else {
                rio_dprintk(RIO_DEBUG_PARAM, "1 stop bit\n");
-               Cor1 |= COR1_1STOP;
+               Cor1 |= RIOC_COR1_1STOP;
        }
 
        if (TtyP->termios->c_cflag & PARENB) {
                rio_dprintk(RIO_DEBUG_PARAM, "Enable parity\n");
-               Cor1 |= COR1_NORMAL;
+               Cor1 |= RIOC_COR1_NORMAL;
        } else {
                rio_dprintk(RIO_DEBUG_PARAM, "Disable parity\n");
-               Cor1 |= COR1_NOP;
+               Cor1 |= RIOC_COR1_NOP;
        }
        if (TtyP->termios->c_cflag & PARODD) {
                rio_dprintk(RIO_DEBUG_PARAM, "Odd parity\n");
-               Cor1 |= COR1_ODD;
+               Cor1 |= RIOC_COR1_ODD;
        } else {
                rio_dprintk(RIO_DEBUG_PARAM, "Even parity\n");
-               Cor1 |= COR1_EVEN;
+               Cor1 |= RIOC_COR1_EVEN;
        }
 
        /*
@@ -292,11 +292,11 @@ int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag)
         */
        if (TtyP->termios->c_iflag & IXON) {
                rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop output control\n");
-               Cor2 |= COR2_IXON;
+               Cor2 |= RIOC_COR2_IXON;
        } else {
                if (PortP->Config & RIO_IXON) {
                        rio_dprintk(RIO_DEBUG_PARAM, "Force enable start/stop output control\n");
-                       Cor2 |= COR2_IXON;
+                       Cor2 |= RIOC_COR2_IXON;
                } else
                        rio_dprintk(RIO_DEBUG_PARAM, "IXON has been disabled.\n");
        }
@@ -304,29 +304,29 @@ int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag)
        if (TtyP->termios->c_iflag & IXANY) {
                if (PortP->Config & RIO_IXANY) {
                        rio_dprintk(RIO_DEBUG_PARAM, "Enable any key to restart output\n");
-                       Cor2 |= COR2_IXANY;
+                       Cor2 |= RIOC_COR2_IXANY;
                } else
                        rio_dprintk(RIO_DEBUG_PARAM, "IXANY has been disabled due to sanity reasons.\n");
        }
 
        if (TtyP->termios->c_iflag & IXOFF) {
                rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop input control 2\n");
-               Cor2 |= COR2_IXOFF;
+               Cor2 |= RIOC_COR2_IXOFF;
        }
 
        if (TtyP->termios->c_cflag & HUPCL) {
                rio_dprintk(RIO_DEBUG_PARAM, "Hangup on last close\n");
-               Cor2 |= COR2_HUPCL;
+               Cor2 |= RIOC_COR2_HUPCL;
        }
 
        if (C_CRTSCTS(TtyP)) {
                rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control enabled\n");
-               Cor2 |= COR2_CTSFLOW;
-               Cor2 |= COR2_RTSFLOW;
+               Cor2 |= RIOC_COR2_CTSFLOW;
+               Cor2 |= RIOC_COR2_RTSFLOW;
        } else {
                rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control disabled\n");
-               Cor2 &= ~COR2_CTSFLOW;
-               Cor2 &= ~COR2_RTSFLOW;
+               Cor2 &= ~RIOC_COR2_CTSFLOW;
+               Cor2 &= ~RIOC_COR2_RTSFLOW;
        }
 
 
@@ -341,36 +341,36 @@ int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag)
         */
        if (TtyP->termios->c_iflag & IGNBRK) {
                rio_dprintk(RIO_DEBUG_PARAM, "Ignore break condition\n");
-               Cor4 |= COR4_IGNBRK;
+               Cor4 |= RIOC_COR4_IGNBRK;
        }
        if (!(TtyP->termios->c_iflag & BRKINT)) {
                rio_dprintk(RIO_DEBUG_PARAM, "Break generates NULL condition\n");
-               Cor4 |= COR4_NBRKINT;
+               Cor4 |= RIOC_COR4_NBRKINT;
        } else {
                rio_dprintk(RIO_DEBUG_PARAM, "Interrupt on      break condition\n");
        }
 
        if (TtyP->termios->c_iflag & INLCR) {
                rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage return on input\n");
-               Cor4 |= COR4_INLCR;
+               Cor4 |= RIOC_COR4_INLCR;
        }
 
        if (TtyP->termios->c_iflag & IGNCR) {
                rio_dprintk(RIO_DEBUG_PARAM, "Ignore carriage return on input\n");
-               Cor4 |= COR4_IGNCR;
+               Cor4 |= RIOC_COR4_IGNCR;
        }
 
        if (TtyP->termios->c_iflag & ICRNL) {
                rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on input\n");
-               Cor4 |= COR4_ICRNL;
+               Cor4 |= RIOC_COR4_ICRNL;
        }
        if (TtyP->termios->c_iflag & IGNPAR) {
                rio_dprintk(RIO_DEBUG_PARAM, "Ignore characters with parity errors\n");
-               Cor4 |= COR4_IGNPAR;
+               Cor4 |= RIOC_COR4_IGNPAR;
        }
        if (TtyP->termios->c_iflag & PARMRK) {
                rio_dprintk(RIO_DEBUG_PARAM, "Mark parity errors\n");
-               Cor4 |= COR4_PARMRK;
+               Cor4 |= RIOC_COR4_PARMRK;
        }
 
        /*
@@ -378,22 +378,22 @@ int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag)
         ** on reception of a config packet.
         ** The download code handles the zero baud condition.
         */
-       Cor4 |= COR4_RAISEMOD;
+       Cor4 |= RIOC_COR4_RAISEMOD;
 
        /*
         ** COR 5
         */
 
-       Cor5 = COR5_CMOE;
+       Cor5 = RIOC_COR5_CMOE;
 
        /*
         ** Set to monitor tbusy/tstop (or not).
         */
 
        if (PortP->MonitorTstate)
-               Cor5 |= COR5_TSTATE_ON;
+               Cor5 |= RIOC_COR5_TSTATE_ON;
        else
-               Cor5 |= COR5_TSTATE_OFF;
+               Cor5 |= RIOC_COR5_TSTATE_OFF;
 
        /*
         ** Could set LNE here if you wanted LNext processing. SVR4 will use it.
@@ -401,24 +401,24 @@ int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag)
        if (TtyP->termios->c_iflag & ISTRIP) {
                rio_dprintk(RIO_DEBUG_PARAM, "Strip input characters\n");
                if (!(PortP->State & RIO_TRIAD_MODE)) {
-                       Cor5 |= COR5_ISTRIP;
+                       Cor5 |= RIOC_COR5_ISTRIP;
                }
        }
 
        if (TtyP->termios->c_oflag & ONLCR) {
                rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage-return, newline on output\n");
                if (PortP->CookMode == COOK_MEDIUM)
-                       Cor5 |= COR5_ONLCR;
+                       Cor5 |= RIOC_COR5_ONLCR;
        }
        if (TtyP->termios->c_oflag & OCRNL) {
                rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on output\n");
                if (PortP->CookMode == COOK_MEDIUM)
-                       Cor5 |= COR5_OCRNL;
+                       Cor5 |= RIOC_COR5_OCRNL;
        }
        if ((TtyP->termios->c_oflag & TABDLY) == TAB3) {
                rio_dprintk(RIO_DEBUG_PARAM, "Tab delay 3 set\n");
                if (PortP->CookMode == COOK_MEDIUM)
-                       Cor5 |= COR5_TAB3;
+                       Cor5 |= RIOC_COR5_TAB3;
        }
 
        /*
index 1cb8580a161dc72b1403b13fff81e862748ab239..c99354843be100844690f6c9aafa987aaf2ee0b3 100644 (file)
@@ -211,7 +211,7 @@ int riotopen(struct tty_struct *tty, struct file *filp)
                rio_dprintk(RIO_DEBUG_TTY, "Waiting for RIO_CLOSING to go away\n");
                if (repeat_this-- <= 0) {
                        rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
-                       RIOPreemptiveCmd(p, PortP, FCLOSE);
+                       RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
                        retval = -EINTR;
                        goto bombout;
                }
@@ -264,7 +264,7 @@ int riotopen(struct tty_struct *tty, struct file *filp)
                   here. If I read the docs correctly the "open"
                   command piggybacks the parameters immediately.
                   -- REW */
-               RIOParam(PortP, OPEN, 1, OK_TO_SLEEP);  /* Open the port */
+               RIOParam(PortP, RIOC_OPEN, 1, OK_TO_SLEEP); /* Open the port */
                rio_spin_lock_irqsave(&PortP->portSem, flags);
 
                /*
@@ -275,7 +275,7 @@ int riotopen(struct tty_struct *tty, struct file *filp)
                        rio_spin_unlock_irqrestore(&PortP->portSem, flags);
                        if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
                                rio_dprintk(RIO_DEBUG_TTY, "Waiting for open to finish broken by signal\n");
-                               RIOPreemptiveCmd(p, PortP, FCLOSE);
+                               RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
                                func_exit();
                                return -EINTR;
                        }
@@ -297,7 +297,8 @@ int riotopen(struct tty_struct *tty, struct file *filp)
         ** insert test for carrier here. -- ???
         ** I already see that test here. What's the deal? -- REW
         */
-       if ((PortP->gs.tty->termios->c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD)) {
+       if ((PortP->gs.tty->termios->c_cflag & CLOCAL) ||
+                       (PortP->ModemState & RIOC_MSVR1_CD)) {
                rio_dprintk(RIO_DEBUG_TTY, "open(%d) Modem carr on\n", SysPort);
                /*
                   tp->tm.c_state |= CARR_ON;
@@ -325,7 +326,7 @@ int riotopen(struct tty_struct *tty, struct file *filp)
                                 ** I think it's OK. -- REW
                                 */
                                rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr broken by signal\n", SysPort);
-                               RIOPreemptiveCmd(p, PortP, FCLOSE);
+                               RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
                                /*
                                   tp->tm.c_state &= ~WOPEN;
                                 */
@@ -416,7 +417,7 @@ int riotclose(void *ptr)
         */
        PortP->State &= ~RIO_MOPEN;
        PortP->State &= ~RIO_CARR_ON;
-       PortP->ModemState &= ~MSVR1_CD;
+       PortP->ModemState &= ~RIOC_MSVR1_CD;
        /*
         ** If the device was open as both a Modem and a tty line
         ** then we need to wimp out here, as the port has not really
@@ -453,7 +454,7 @@ int riotclose(void *ptr)
                        if (repeat_this-- <= 0) {
                                rv = -EINTR;
                                rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
-                               RIOPreemptiveCmd(p, PortP, FCLOSE);
+                               RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
                                goto close_end;
                        }
                        rio_dprintk(RIO_DEBUG_TTY, "Calling timeout to flush in closing\n");
@@ -492,8 +493,8 @@ int riotclose(void *ptr)
        /* Can't call RIOShortCommand with the port locked. */
        rio_spin_unlock_irqrestore(&PortP->portSem, flags);
 
-       if (RIOShortCommand(p, PortP, CLOSE, 1, 0) == RIO_FAIL) {
-               RIOPreemptiveCmd(p, PortP, FCLOSE);
+       if (RIOShortCommand(p, PortP, RIOC_CLOSE, 1, 0) == RIO_FAIL) {
+               RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
                rio_spin_lock_irqsave(&PortP->portSem, flags);
                goto close_end;
        }
@@ -503,7 +504,7 @@ int riotclose(void *ptr)
                        try--;
                        if (time_after(jiffies, end_time)) {
                                rio_dprintk(RIO_DEBUG_TTY, "Run out of tries - force the bugger shut!\n");
-                               RIOPreemptiveCmd(p, PortP, FCLOSE);
+                               RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
                                break;
                        }
                        rio_dprintk(RIO_DEBUG_TTY, "Close: PortState:ISOPEN is %d\n", PortP->PortState & PORT_ISOPEN);
@@ -515,14 +516,14 @@ int riotclose(void *ptr)
                        }
                        if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
                                rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n");
-                               RIOPreemptiveCmd(p, PortP, FCLOSE);
+                               RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
                                break;
                        }
                }
        rio_spin_lock_irqsave(&PortP->portSem, flags);
        rio_dprintk(RIO_DEBUG_TTY, "Close: try was %d on completion\n", try);
 
-       /* RIOPreemptiveCmd(p, PortP, FCLOSE); */
+       /* RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); */
 
 /*
 ** 15.10.1998 ARG - ESIL 0761 part fix
index 3f9d0a9ac36d5988408f29a133e5a9c8fa1763ae..f073c710ab8d958a2fb695f43ad279a12929da06 100644 (file)
@@ -4,9 +4,9 @@
  *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
  *
  *      This code is loosely based on the Linux serial driver, written by
- *      Linus Torvalds, Theodore T'so and others. The RISCom/8 card 
- *      programming info was obtained from various drivers for other OSes 
- *     (FreeBSD, ISC, etc), but no source code from those drivers were 
+ *      Linus Torvalds, Theodore T'so and others. The RISCom/8 card
+ *      programming info was obtained from various drivers for other OSes
+ *     (FreeBSD, ISC, etc), but no source code from those drivers were
  *     directly included in this driver.
  *
  *
@@ -33,7 +33,7 @@
 
 #include <linux/module.h>
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/ioport.h>
@@ -49,7 +49,7 @@
 #include <linux/tty_flip.h>
 #include <linux/spinlock.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "riscom8.h"
 #include "riscom8_reg.h"
 /* Am I paranoid or not ? ;-) */
 #define RISCOM_PARANOIA_CHECK
 
-/* 
- * Crazy InteliCom/8 boards sometimes has swapped CTS & DSR signals.
+/*
+ * Crazy InteliCom/8 boards sometimes have swapped CTS & DSR signals.
  * You can slightly speed up things by #undefing the following option,
- * if you are REALLY sure that your board is correct one. 
+ * if you are REALLY sure that your board is correct one.
  */
 
 #define RISCOM_BRAIN_DAMAGED_CTS
 
-/* 
+/*
  * The following defines are mostly for testing purposes. But if you need
  * some nice reporting in your syslog, you can define them also.
  */
@@ -112,7 +112,7 @@ static unsigned short rc_ioport[] =  {
 #define RC_NIOPORT     ARRAY_SIZE(rc_ioport)
 
 
-static inline int rc_paranoia_check(struct riscom_port const * port,
+static int rc_paranoia_check(struct riscom_port const *port,
                                    char *name, const char *routine)
 {
 #ifdef RISCOM_PARANOIA_CHECK
@@ -134,52 +134,53 @@ static inline int rc_paranoia_check(struct riscom_port const * port,
 }
 
 /*
- * 
+ *
  *  Service functions for RISCom/8 driver.
- * 
+ *
  */
 
 /* Get board number from pointer */
-static inline int board_No (struct riscom_board const * bp)
+static inline int board_No(struct riscom_board const *bp)
 {
        return bp - rc_board;
 }
 
 /* Get port number from pointer */
-static inline int port_No (struct riscom_port const * port)
+static inline int port_No(struct riscom_port const *port)
 {
-       return RC_PORT(port - rc_port); 
+       return RC_PORT(port - rc_port);
 }
 
 /* Get pointer to board from pointer to port */
-static inline struct riscom_board * port_Board(struct riscom_port const * port)
+static inline struct riscom_board *port_Board(struct riscom_port const *port)
 {
        return &rc_board[RC_BOARD(port - rc_port)];
 }
 
 /* Input Byte from CL CD180 register */
-static inline unsigned char rc_in(struct riscom_board const * bp, unsigned short reg)
+static inline unsigned char rc_in(struct riscom_board const *bp,
+                                                       unsigned short reg)
 {
        return inb(bp->base + RC_TO_ISA(reg));
 }
 
 /* Output Byte to CL CD180 register */
-static inline void rc_out(struct riscom_board const * bp, unsigned short reg,
+static inline void rc_out(struct riscom_board const *bp, unsigned short reg,
                          unsigned char val)
 {
        outb(val, bp->base + RC_TO_ISA(reg));
 }
 
 /* Wait for Channel Command Register ready */
-static inline void rc_wait_CCR(struct riscom_board const * bp)
+static void rc_wait_CCR(struct riscom_board const *bp)
 {
        unsigned long delay;
 
        /* FIXME: need something more descriptive then 100000 :) */
-       for (delay = 100000; delay; delay--) 
+       for (delay = 100000; delay; delay--)
                if (!rc_in(bp, CD180_CCR))
                        return;
-       
+
        printk(KERN_INFO "rc%d: Timeout waiting for CCR.\n", board_No(bp));
 }
 
@@ -187,11 +188,11 @@ static inline void rc_wait_CCR(struct riscom_board const * bp)
  *  RISCom/8 probe functions.
  */
 
-static inline int rc_request_io_range(struct riscom_board * const bp)
+static int rc_request_io_range(struct riscom_board * const bp)
 {
        int i;
-       
-       for (i = 0; i < RC_NIOPORT; i++)  
+
+       for (i = 0; i < RC_NIOPORT; i++)
                if (!request_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1,
                                   "RISCom/8"))  {
                        goto out_release;
@@ -200,42 +201,42 @@ static inline int rc_request_io_range(struct riscom_board * const bp)
 out_release:
        printk(KERN_INFO "rc%d: Skipping probe at 0x%03x. IO address in use.\n",
                         board_No(bp), bp->base);
-       while(--i >= 0)
+       while (--i >= 0)
                release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1);
        return 1;
 }
 
-static inline void rc_release_io_range(struct riscom_board * const bp)
+static void rc_release_io_range(struct riscom_board * const bp)
 {
        int i;
-       
-       for (i = 0; i < RC_NIOPORT; i++)  
+
+       for (i = 0; i < RC_NIOPORT; i++)
                release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1);
 }
-       
+
 /* Reset and setup CD180 chip */
-static void __init rc_init_CD180(struct riscom_board const * bp)
+static void __init rc_init_CD180(struct riscom_board const *bp)
 {
        unsigned long flags;
-       
+
        spin_lock_irqsave(&riscom_lock, flags);
 
-       rc_out(bp, RC_CTOUT, 0);                   /* Clear timeout             */
-       rc_wait_CCR(bp);                           /* Wait for CCR ready        */
-       rc_out(bp, CD180_CCR, CCR_HARDRESET);      /* Reset CD180 chip          */
+       rc_out(bp, RC_CTOUT, 0);                   /* Clear timeout        */
+       rc_wait_CCR(bp);                           /* Wait for CCR ready   */
+       rc_out(bp, CD180_CCR, CCR_HARDRESET);      /* Reset CD180 chip     */
        spin_unlock_irqrestore(&riscom_lock, flags);
-       msleep(50);                                /* Delay 0.05 sec            */
+       msleep(50);                                /* Delay 0.05 sec       */
        spin_lock_irqsave(&riscom_lock, flags);
-       rc_out(bp, CD180_GIVR, RC_ID);             /* Set ID for this chip      */
-       rc_out(bp, CD180_GICR, 0);                 /* Clear all bits            */
-       rc_out(bp, CD180_PILR1, RC_ACK_MINT);      /* Prio for modem intr       */
-       rc_out(bp, CD180_PILR2, RC_ACK_TINT);      /* Prio for transmitter intr */
-       rc_out(bp, CD180_PILR3, RC_ACK_RINT);      /* Prio for receiver intr    */
-       
+       rc_out(bp, CD180_GIVR, RC_ID);             /* Set ID for this chip */
+       rc_out(bp, CD180_GICR, 0);                 /* Clear all bits       */
+       rc_out(bp, CD180_PILR1, RC_ACK_MINT);      /* Prio for modem intr  */
+       rc_out(bp, CD180_PILR2, RC_ACK_TINT);      /* Prio for tx intr     */
+       rc_out(bp, CD180_PILR3, RC_ACK_RINT);      /* Prio for rx intr     */
+
        /* Setting up prescaler. We need 4 ticks per 1 ms */
        rc_out(bp, CD180_PPRH, (RC_OSCFREQ/(1000000/RISCOM_TPS)) >> 8);
        rc_out(bp, CD180_PPRL, (RC_OSCFREQ/(1000000/RISCOM_TPS)) & 0xff);
-       
+
        spin_unlock_irqrestore(&riscom_lock, flags);
 }
 
@@ -245,12 +246,12 @@ static int __init rc_probe(struct riscom_board *bp)
        unsigned char val1, val2;
        int irqs = 0;
        int retries;
-       
+
        bp->irq = 0;
 
        if (rc_request_io_range(bp))
                return 1;
-       
+
        /* Are the I/O ports here ? */
        rc_out(bp, CD180_PPRL, 0x5a);
        outb(0xff, 0x80);
@@ -258,34 +259,34 @@ static int __init rc_probe(struct riscom_board *bp)
        rc_out(bp, CD180_PPRL, 0xa5);
        outb(0x00, 0x80);
        val2 = rc_in(bp, CD180_PPRL);
-       
+
        if ((val1 != 0x5a) || (val2 != 0xa5))  {
                printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not found.\n",
                       board_No(bp), bp->base);
                goto out_release;
        }
-       
+
        /* It's time to find IRQ for this board */
-       for (retries = 0; retries < 5 && irqs <= 0; retries++)  {
+       for (retries = 0; retries < 5 && irqs <= 0; retries++) {
                irqs = probe_irq_on();
-               rc_init_CD180(bp);                      /* Reset CD180 chip       */
-               rc_out(bp, CD180_CAR, 2);               /* Select port 2          */
+               rc_init_CD180(bp);               /* Reset CD180 chip         */
+               rc_out(bp, CD180_CAR, 2);        /* Select port 2            */
                rc_wait_CCR(bp);
-               rc_out(bp, CD180_CCR, CCR_TXEN);        /* Enable transmitter     */
-               rc_out(bp, CD180_IER, IER_TXRDY);       /* Enable tx empty intr   */
+               rc_out(bp, CD180_CCR, CCR_TXEN); /* Enable transmitter       */
+               rc_out(bp, CD180_IER, IER_TXRDY);/* Enable tx empty intr     */
                msleep(50);
                irqs = probe_irq_off(irqs);
-               val1 = rc_in(bp, RC_BSR);               /* Get Board Status reg   */
-               val2 = rc_in(bp, RC_ACK_TINT);          /* ACK interrupt          */
-               rc_init_CD180(bp);                      /* Reset CD180 again      */
-       
+               val1 = rc_in(bp, RC_BSR);       /* Get Board Status reg      */
+               val2 = rc_in(bp, RC_ACK_TINT);  /* ACK interrupt             */
+               rc_init_CD180(bp);              /* Reset CD180 again         */
+
                if ((val1 & RC_BSR_TINT) || (val2 != (RC_ID | GIVR_IT_TX)))  {
                        printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not "
                                        "found.\n", board_No(bp), bp->base);
                        goto out_release;
                }
        }
-       
+
        if (irqs <= 0)  {
                printk(KERN_ERR "rc%d: Can't find IRQ for RISCom/8 board "
                                "at 0x%03x.\n", board_No(bp), bp->base);
@@ -293,113 +294,112 @@ static int __init rc_probe(struct riscom_board *bp)
        }
        bp->irq = irqs;
        bp->flags |= RC_BOARD_PRESENT;
-       
+
        printk(KERN_INFO "rc%d: RISCom/8 Rev. %c board detected at "
                         "0x%03x, IRQ %d.\n",
               board_No(bp),
               (rc_in(bp, CD180_GFRCR) & 0x0f) + 'A',   /* Board revision */
               bp->base, bp->irq);
-       
+
        return 0;
 out_release:
        rc_release_io_range(bp);
        return 1;
 }
 
-/* 
- * 
+/*
+ *
  *  Interrupt processing routines.
- * 
+ *
  */
 
-static inline struct riscom_port * rc_get_port(struct riscom_board const * bp,
-                                              unsigned char const * what)
+static struct riscom_port *rc_get_port(struct riscom_board const *bp,
+                                              unsigned char const *what)
 {
        unsigned char channel;
-       struct riscom_port * port;
-       
+       struct riscom_port *port;
+
        channel = rc_in(bp, CD180_GICR) >> GICR_CHAN_OFF;
        if (channel < CD180_NCH)  {
                port = &rc_port[board_No(bp) * RC_NPORT + channel];
-               if (port->flags & ASYNC_INITIALIZED)  {
+               if (port->flags & ASYNC_INITIALIZED)
                        return port;
-               }
        }
-       printk(KERN_ERR "rc%d: %s interrupt from invalid port %d\n", 
+       printk(KERN_ERR "rc%d: %s interrupt from invalid port %d\n",
               board_No(bp), what, channel);
        return NULL;
 }
 
-static inline void rc_receive_exc(struct riscom_board const * bp)
+static void rc_receive_exc(struct riscom_board const *bp)
 {
        struct riscom_port *port;
        struct tty_struct *tty;
        unsigned char status;
        unsigned char ch, flag;
-       
-       if (!(port = rc_get_port(bp, "Receive")))
+
+       port = rc_get_port(bp, "Receive");
+       if (port == NULL)
                return;
 
        tty = port->tty;
-       
-#ifdef RC_REPORT_OVERRUN       
+
+#ifdef RC_REPORT_OVERRUN
        status = rc_in(bp, CD180_RCSR);
        if (status & RCSR_OE)
                port->overrun++;
        status &= port->mark_mask;
-#else  
+#else
        status = rc_in(bp, CD180_RCSR) & port->mark_mask;
-#endif 
+#endif
        ch = rc_in(bp, CD180_RDR);
-       if (!status)  {
+       if (!status)
                return;
-       }
        if (status & RCSR_TOUT)  {
                printk(KERN_WARNING "rc%d: port %d: Receiver timeout. "
-                                   "Hardware problems ?\n", 
+                                   "Hardware problems ?\n",
                       board_No(bp), port_No(port));
                return;
-               
+
        } else if (status & RCSR_BREAK)  {
                printk(KERN_INFO "rc%d: port %d: Handling break...\n",
                       board_No(bp), port_No(port));
                flag = TTY_BREAK;
                if (port->flags & ASYNC_SAK)
                        do_SAK(tty);
-               
-       } else if (status & RCSR_PE) 
+
+       } else if (status & RCSR_PE)
                flag = TTY_PARITY;
-       
-       else if (status & RCSR_FE) 
+
+       else if (status & RCSR_FE)
                flag = TTY_FRAME;
-       
-        else if (status & RCSR_OE)
+
+       else if (status & RCSR_OE)
                flag = TTY_OVERRUN;
-       
        else
                flag = TTY_NORMAL;
-       
+
        tty_insert_flip_char(tty, ch, flag);
        tty_flip_buffer_push(tty);
 }
 
-static inline void rc_receive(struct riscom_board const * bp)
+static void rc_receive(struct riscom_board const *bp)
 {
        struct riscom_port *port;
        struct tty_struct *tty;
        unsigned char count;
-       
-       if (!(port = rc_get_port(bp, "Receive")))
+
+       port = rc_get_port(bp, "Receive");
+       if (port == NULL)
                return;
-       
+
        tty = port->tty;
-       
+
        count = rc_in(bp, CD180_RDCR);
-       
+
 #ifdef RC_REPORT_FIFO
        port->hits[count > 8 ? 9 : count]++;
-#endif 
-       
+#endif
+
        while (count--)  {
                if (tty_buffer_request_room(tty, 1) == 0)  {
                        printk(KERN_WARNING "rc%d: port %d: Working around "
@@ -412,26 +412,26 @@ static inline void rc_receive(struct riscom_board const * bp)
        tty_flip_buffer_push(tty);
 }
 
-static inline void rc_transmit(struct riscom_board const * bp)
+static void rc_transmit(struct riscom_board const *bp)
 {
        struct riscom_port *port;
        struct tty_struct *tty;
        unsigned char count;
-       
-       
-       if (!(port = rc_get_port(bp, "Transmit")))
+
+       port = rc_get_port(bp, "Transmit");
+       if (port == NULL)
                return;
-       
+
        tty = port->tty;
-       
-       if (port->IER & IER_TXEMPTY)  {
+
+       if (port->IER & IER_TXEMPTY) {
                /* FIFO drained */
                rc_out(bp, CD180_CAR, port_No(port));
                port->IER &= ~IER_TXEMPTY;
                rc_out(bp, CD180_IER, port->IER);
                return;
        }
-       
+
        if ((port->xmit_cnt <= 0 && !port->break_length)
            || tty->stopped || tty->hw_stopped)  {
                rc_out(bp, CD180_CAR, port_No(port));
@@ -439,7 +439,7 @@ static inline void rc_transmit(struct riscom_board const * bp)
                rc_out(bp, CD180_IER, port->IER);
                return;
        }
-       
+
        if (port->break_length)  {
                if (port->break_length > 0)  {
                        if (port->COR2 & COR2_ETC)  {
@@ -451,7 +451,8 @@ static inline void rc_transmit(struct riscom_board const * bp)
                        rc_out(bp, CD180_TDR, CD180_C_ESC);
                        rc_out(bp, CD180_TDR, CD180_C_DELAY);
                        rc_out(bp, CD180_TDR, count);
-                       if (!(port->break_length -= count))
+                       port->break_length -= count;
+                       if (port->break_length == 0)
                                port->break_length--;
                } else  {
                        rc_out(bp, CD180_TDR, CD180_C_ESC);
@@ -463,7 +464,7 @@ static inline void rc_transmit(struct riscom_board const * bp)
                }
                return;
        }
-       
+
        count = CD180_NFIFO;
        do {
                rc_out(bp, CD180_TDR, port->xmit_buf[port->xmit_tail++]);
@@ -471,7 +472,7 @@ static inline void rc_transmit(struct riscom_board const * bp)
                if (--port->xmit_cnt <= 0)
                        break;
        } while (--count > 0);
-       
+
        if (port->xmit_cnt <= 0)  {
                rc_out(bp, CD180_CAR, port_No(port));
                port->IER &= ~IER_TXRDY;
@@ -481,25 +482,26 @@ static inline void rc_transmit(struct riscom_board const * bp)
                tty_wakeup(tty);
 }
 
-static inline void rc_check_modem(struct riscom_board const * bp)
+static void rc_check_modem(struct riscom_board const *bp)
 {
        struct riscom_port *port;
        struct tty_struct *tty;
        unsigned char mcr;
-       
-       if (!(port = rc_get_port(bp, "Modem")))
+
+       port = rc_get_port(bp, "Modem");
+       if (port == NULL)
                return;
-       
+
        tty = port->tty;
-       
+
        mcr = rc_in(bp, CD180_MCR);
-       if (mcr & MCR_CDCHG)  {
-               if (rc_in(bp, CD180_MSVR) & MSVR_CD) 
+       if (mcr & MCR_CDCHG) {
+               if (rc_in(bp, CD180_MSVR) & MSVR_CD)
                        wake_up_interruptible(&port->open_wait);
                else
                        tty_hangup(tty);
        }
-       
+
 #ifdef RISCOM_BRAIN_DAMAGED_CTS
        if (mcr & MCR_CTSCHG)  {
                if (rc_in(bp, CD180_MSVR) & MSVR_CTS)  {
@@ -526,13 +528,13 @@ static inline void rc_check_modem(struct riscom_board const * bp)
                rc_out(bp, CD180_IER, port->IER);
        }
 #endif /* RISCOM_BRAIN_DAMAGED_CTS */
-       
+
        /* Clear change bits */
        rc_out(bp, CD180_MCR, 0);
 }
 
 /* The main interrupt processing routine */
-static irqreturn_t rc_interrupt(int dummy, void * dev_id)
+static irqreturn_t rc_interrupt(int dummy, void *dev_id)
 {
        unsigned char status;
        unsigned char ack;
@@ -547,13 +549,11 @@ static irqreturn_t rc_interrupt(int dummy, void * dev_id)
                                 (RC_BSR_TOUT | RC_BSR_TINT |
                                  RC_BSR_MINT | RC_BSR_RINT))) {
                handled = 1;
-               if (status & RC_BSR_TOUT) 
+               if (status & RC_BSR_TOUT)
                        printk(KERN_WARNING "rc%d: Got timeout. Hardware "
                                            "error?\n", board_No(bp));
-               
                else if (status & RC_BSR_RINT) {
                        ack = rc_in(bp, RC_ACK_RINT);
-               
                        if (ack == (RC_ID | GIVR_IT_RCV))
                                rc_receive(bp);
                        else if (ack == (RC_ID | GIVR_IT_REXC))
@@ -562,29 +562,23 @@ static irqreturn_t rc_interrupt(int dummy, void * dev_id)
                                printk(KERN_WARNING "rc%d: Bad receive ack "
                                                    "0x%02x.\n",
                                       board_No(bp), ack);
-               
                } else if (status & RC_BSR_TINT) {
                        ack = rc_in(bp, RC_ACK_TINT);
-               
                        if (ack == (RC_ID | GIVR_IT_TX))
                                rc_transmit(bp);
                        else
                                printk(KERN_WARNING "rc%d: Bad transmit ack "
                                                    "0x%02x.\n",
                                       board_No(bp), ack);
-               
                } else /* if (status & RC_BSR_MINT) */ {
                        ack = rc_in(bp, RC_ACK_MINT);
-               
-                       if (ack == (RC_ID | GIVR_IT_MODEM)) 
+                       if (ack == (RC_ID | GIVR_IT_MODEM))
                                rc_check_modem(bp);
                        else
                                printk(KERN_WARNING "rc%d: Bad modem ack "
                                                    "0x%02x.\n",
                                       board_No(bp), ack);
-               
-               } 
-
+               }
                rc_out(bp, CD180_EOIR, 0);   /* Mark end of interrupt */
                rc_out(bp, RC_CTOUT, 0);     /* Clear timeout flag    */
        }
@@ -596,24 +590,24 @@ static irqreturn_t rc_interrupt(int dummy, void * dev_id)
  */
 
 /* Called with disabled interrupts */
-static int rc_setup_board(struct riscom_board * bp)
+static int rc_setup_board(struct riscom_board *bp)
 {
        int error;
 
-       if (bp->flags & RC_BOARD_ACTIVE) 
+       if (bp->flags & RC_BOARD_ACTIVE)
                return 0;
-       
+
        error = request_irq(bp->irq, rc_interrupt, IRQF_DISABLED,
                            "RISCom/8", bp);
-       if (error) 
+       if (error)
                return error;
-       
+
        rc_out(bp, RC_CTOUT, 0);                /* Just in case         */
        bp->DTR = ~0;
        rc_out(bp, RC_DTR, bp->DTR);            /* Drop DTR on all ports */
-       
+
        bp->flags |= RC_BOARD_ACTIVE;
-       
+
        return 0;
 }
 
@@ -622,40 +616,40 @@ static void rc_shutdown_board(struct riscom_board *bp)
 {
        if (!(bp->flags & RC_BOARD_ACTIVE))
                return;
-       
+
        bp->flags &= ~RC_BOARD_ACTIVE;
-       
+
        free_irq(bp->irq, NULL);
-       
+
        bp->DTR = ~0;
        rc_out(bp, RC_DTR, bp->DTR);           /* Drop DTR on all ports */
-       
+
 }
 
 /*
- * Setting up port characteristics. 
+ * Setting up port characteristics.
  * Must be called with disabled interrupts
  */
 static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port)
 {
-       struct tty_struct *tty;
+       struct tty_struct *tty = port->tty;
        unsigned long baud;
        long tmp;
        unsigned char cor1 = 0, cor3 = 0;
        unsigned char mcor1 = 0, mcor2 = 0;
-       
-       if (!(tty = port->tty) || !tty->termios)
+
+       if (tty == NULL || tty->termios == NULL)
                return;
 
        port->IER  = 0;
        port->COR2 = 0;
        port->MSVR = MSVR_RTS;
-       
+
        baud = tty_get_baud_rate(tty);
-       
+
        /* Select port on the board */
        rc_out(bp, CD180_CAR, port_No(port));
-       
+
        if (!baud)  {
                /* Drop DTR & exit */
                bp->DTR |= (1u << port_No(port));
@@ -666,69 +660,68 @@ static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port)
                bp->DTR &= ~(1u << port_No(port));
                rc_out(bp, RC_DTR, bp->DTR);
        }
-       
+
        /*
-        * Now we must calculate some speed depended things 
+        * Now we must calculate some speed depended things
         */
-       
+
        /* Set baud rate for port */
        tmp = (((RC_OSCFREQ + baud/2) / baud +
                CD180_TPC/2) / CD180_TPC);
 
-       rc_out(bp, CD180_RBPRH, (tmp >> 8) & 0xff); 
-       rc_out(bp, CD180_TBPRH, (tmp >> 8) & 0xff); 
-       rc_out(bp, CD180_RBPRL, tmp & 0xff); 
+       rc_out(bp, CD180_RBPRH, (tmp >> 8) & 0xff);
+       rc_out(bp, CD180_TBPRH, (tmp >> 8) & 0xff);
+       rc_out(bp, CD180_RBPRL, tmp & 0xff);
        rc_out(bp, CD180_TBPRL, tmp & 0xff);
-       
+
        baud = (baud + 5) / 10;   /* Estimated CPS */
-       
+
        /* Two timer ticks seems enough to wakeup something like SLIP driver */
-       tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO;           
+       tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO;
        port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
                                              SERIAL_XMIT_SIZE - 1 : tmp);
-       
+
        /* Receiver timeout will be transmission time for 1.5 chars */
        tmp = (RISCOM_TPS + RISCOM_TPS/2 + baud/2) / baud;
        tmp = (tmp > 0xff) ? 0xff : tmp;
        rc_out(bp, CD180_RTPR, tmp);
-       
-       switch (C_CSIZE(tty))  {
-        case CS5:
+
+       switch (C_CSIZE(tty)) {
+       case CS5:
                cor1 |= COR1_5BITS;
                break;
-        case CS6:
+       case CS6:
                cor1 |= COR1_6BITS;
                break;
-        case CS7:
+       case CS7:
                cor1 |= COR1_7BITS;
                break;
-        case CS8:
+       case CS8:
                cor1 |= COR1_8BITS;
                break;
        }
-       
-       if (C_CSTOPB(tty)) 
+       if (C_CSTOPB(tty))
                cor1 |= COR1_2SB;
-       
+
        cor1 |= COR1_IGNORE;
-       if (C_PARENB(tty))  {
+       if (C_PARENB(tty)) {
                cor1 |= COR1_NORMPAR;
-               if (C_PARODD(tty)) 
+               if (C_PARODD(tty))
                        cor1 |= COR1_ODDP;
-               if (I_INPCK(tty)) 
+               if (I_INPCK(tty))
                        cor1 &= ~COR1_IGNORE;
        }
        /* Set marking of some errors */
        port->mark_mask = RCSR_OE | RCSR_TOUT;
-       if (I_INPCK(tty)) 
+       if (I_INPCK(tty))
                port->mark_mask |= RCSR_FE | RCSR_PE;
-       if (I_BRKINT(tty) || I_PARMRK(tty)) 
+       if (I_BRKINT(tty) || I_PARMRK(tty))
                port->mark_mask |= RCSR_BREAK;
-       if (I_IGNPAR(tty)) 
+       if (I_IGNPAR(tty))
                port->mark_mask &= ~(RCSR_FE | RCSR_PE);
-       if (I_IGNBRK(tty))  {
+       if (I_IGNBRK(tty)) {
                port->mark_mask &= ~RCSR_BREAK;
-               if (I_IGNPAR(tty)) 
+               if (I_IGNPAR(tty))
                        /* Real raw mode. Ignore all */
                        port->mark_mask &= ~RCSR_OE;
        }
@@ -738,7 +731,8 @@ static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port)
                port->IER |= IER_DSR | IER_CTS;
                mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
                mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
-               tty->hw_stopped = !(rc_in(bp, CD180_MSVR) & (MSVR_CTS|MSVR_DSR));
+               tty->hw_stopped = !(rc_in(bp, CD180_MSVR) &
+                                               (MSVR_CTS|MSVR_DSR));
 #else
                port->COR2 |= COR2_CTSAE;
 #endif
@@ -761,13 +755,13 @@ static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port)
                mcor1 |= MCOR1_CDZD;
                mcor2 |= MCOR2_CDOD;
        }
-       
-       if (C_CREAD(tty)) 
+
+       if (C_CREAD(tty))
                /* Enable receiver */
                port->IER |= IER_RXD;
-       
+
        /* Set input FIFO size (1-8 bytes) */
-       cor3 |= RISCOM_RXFIFO; 
+       cor3 |= RISCOM_RXFIFO;
        /* Setting up CD180 channel registers */
        rc_out(bp, CD180_COR1, cor1);
        rc_out(bp, CD180_COR2, port->COR2);
@@ -791,36 +785,30 @@ static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port)
 static int rc_setup_port(struct riscom_board *bp, struct riscom_port *port)
 {
        unsigned long flags;
-       
+
        if (port->flags & ASYNC_INITIALIZED)
                return 0;
-       
+
        if (!port->xmit_buf) {
                /* We may sleep in get_zeroed_page() */
-               unsigned long tmp;
-               
-               if (!(tmp = get_zeroed_page(GFP_KERNEL)))
+               unsigned long tmp = get_zeroed_page(GFP_KERNEL);
+               if (tmp == 0)
                        return -ENOMEM;
-                   
-               if (port->xmit_buf) {
+               if (port->xmit_buf)
                        free_page(tmp);
-                       return -ERESTARTSYS;
-               }
-               port->xmit_buf = (unsigned char *) tmp;
+               else
+                       port->xmit_buf = (unsigned char *) tmp;
        }
-
        spin_lock_irqsave(&riscom_lock, flags);
 
-       if (port->tty) 
+       if (port->tty)
                clear_bit(TTY_IO_ERROR, &port->tty->flags);
-               
-       if (port->count == 1) 
+       if (port->count == 1)
                bp->count++;
-               
        port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
        rc_change_speed(bp, port);
        port->flags |= ASYNC_INITIALIZED;
-               
+
        spin_unlock_irqrestore(&riscom_lock, flags);
        return 0;
 }
@@ -829,38 +817,39 @@ static int rc_setup_port(struct riscom_board *bp, struct riscom_port *port)
 static void rc_shutdown_port(struct riscom_board *bp, struct riscom_port *port)
 {
        struct tty_struct *tty;
-       
-       if (!(port->flags & ASYNC_INITIALIZED)) 
+
+       if (!(port->flags & ASYNC_INITIALIZED))
                return;
-       
+
 #ifdef RC_REPORT_OVERRUN
        printk(KERN_INFO "rc%d: port %d: Total %ld overruns were detected.\n",
               board_No(bp), port_No(port), port->overrun);
-#endif 
+#endif
 #ifdef RC_REPORT_FIFO
        {
                int i;
-               
+
                printk(KERN_INFO "rc%d: port %d: FIFO hits [ ",
                       board_No(bp), port_No(port));
-               for (i = 0; i < 10; i++)  {
+               for (i = 0; i < 10; i++)
                        printk("%ld ", port->hits[i]);
-               }
                printk("].\n");
        }
-#endif 
+#endif
        if (port->xmit_buf)  {
                free_page((unsigned long) port->xmit_buf);
                port->xmit_buf = NULL;
        }
 
-       if (!(tty = port->tty) || C_HUPCL(tty))  {
+       tty = port->tty;
+
+       if (tty == NULL || C_HUPCL(tty)) {
                /* Drop DTR */
                bp->DTR |= (1u << port_No(port));
                rc_out(bp, RC_DTR, bp->DTR);
        }
-       
-        /* Select port */
+
+       /* Select port */
        rc_out(bp, CD180_CAR, port_No(port));
        /* Reset port */
        rc_wait_CCR(bp);
@@ -868,28 +857,26 @@ static void rc_shutdown_port(struct riscom_board *bp, struct riscom_port *port)
        /* Disable all interrupts from this port */
        port->IER = 0;
        rc_out(bp, CD180_IER, port->IER);
-       
-       if (tty)  
+
+       if (tty)
                set_bit(TTY_IO_ERROR, &tty->flags);
        port->flags &= ~ASYNC_INITIALIZED;
-       
+
        if (--bp->count < 0)  {
                printk(KERN_INFO "rc%d: rc_shutdown_port: "
                                 "bad board count: %d\n",
                       board_No(bp), bp->count);
                bp->count = 0;
        }
-       
        /*
         * If this is the last opened port on the board
         * shutdown whole board
         */
-       if (!bp->count) 
+       if (!bp->count)
                rc_shutdown_board(bp);
 }
 
-       
-static int block_til_ready(struct tty_struct *tty, struct file * filp,
+static int block_til_ready(struct tty_struct *tty, struct file *filp,
                           struct riscom_port *port)
 {
        DECLARE_WAITQUEUE(wait, current);
@@ -921,7 +908,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
                return 0;
        }
 
-       if (C_CLOCAL(tty))  
+       if (C_CLOCAL(tty))
                do_clocal = 1;
 
        /*
@@ -959,7 +946,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
                        if (port->flags & ASYNC_HUP_NOTIFY)
                                retval = -EAGAIN;
                        else
-                               retval = -ERESTARTSYS;  
+                               retval = -ERESTARTSYS;
                        break;
                }
                if (!(port->flags & ASYNC_CLOSING) &&
@@ -978,50 +965,63 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
        port->blocked_open--;
        if (retval)
                return retval;
-       
+
        port->flags |= ASYNC_NORMAL_ACTIVE;
        return 0;
-}      
+}
 
-static int rc_open(struct tty_struct * tty, struct file * filp)
+static int rc_open(struct tty_struct *tty, struct file *filp)
 {
        int board;
        int error;
-       struct riscom_port * port;
-       struct riscom_board * bp;
-       
+       struct riscom_port *port;
+       struct riscom_board *bp;
+
        board = RC_BOARD(tty->index);
        if (board >= RC_NBOARD || !(rc_board[board].flags & RC_BOARD_PRESENT))
                return -ENODEV;
-       
+
        bp = &rc_board[board];
        port = rc_port + board * RC_NPORT + RC_PORT(tty->index);
        if (rc_paranoia_check(port, tty->name, "rc_open"))
                return -ENODEV;
-       
-       if ((error = rc_setup_board(bp))) 
+
+       error = rc_setup_board(bp);
+       if (error)
                return error;
-               
+
        port->count++;
        tty->driver_data = port;
        port->tty = tty;
-       
-       if ((error = rc_setup_port(bp, port))) 
-               return error;
-       
-       if ((error = block_til_ready(tty, filp, port)))
-               return error;
-       
-       return 0;
+
+       error = rc_setup_port(bp, port);
+       if (error == 0)
+               error = block_til_ready(tty, filp, port);
+       return error;
 }
 
-static void rc_close(struct tty_struct * tty, struct file * filp)
+static void rc_flush_buffer(struct tty_struct *tty)
+{
+       struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+       unsigned long flags;
+
+       if (rc_paranoia_check(port, tty->name, "rc_flush_buffer"))
+               return;
+
+       spin_lock_irqsave(&riscom_lock, flags);
+       port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+       spin_unlock_irqrestore(&riscom_lock, flags);
+
+       tty_wakeup(tty);
+}
+
+static void rc_close(struct tty_struct *tty, struct file *filp)
 {
        struct riscom_port *port = (struct riscom_port *) tty->driver_data;
        struct riscom_board *bp;
        unsigned long flags;
        unsigned long timeout;
-       
+
        if (!port || rc_paranoia_check(port, tty->name, "close"))
                return;
 
@@ -1029,7 +1029,7 @@ static void rc_close(struct tty_struct * tty, struct file * filp)
 
        if (tty_hung_up_p(filp))
                goto out;
-       
+
        bp = port_Board(port);
        if ((tty->count == 1) && (port->count != 1))  {
                printk(KERN_INFO "rc%d: rc_close: bad port count;"
@@ -1047,7 +1047,7 @@ static void rc_close(struct tty_struct * tty, struct file * filp)
                goto out;
        port->flags |= ASYNC_CLOSING;
        /*
-        * Now we wait for the transmit buffer to clear; and we notify 
+        * Now we wait for the transmit buffer to clear; and we notify
         * the line discipline to only process XON/XOFF characters.
         */
        tty->closing = 1;
@@ -1070,24 +1070,22 @@ static void rc_close(struct tty_struct * tty, struct file * filp)
                 * has completely drained; this is especially
                 * important if there is a transmit FIFO!
                 */
-               timeout = jiffies+HZ;
-               while(port->IER & IER_TXEMPTY)  {
+               timeout = jiffies + HZ;
+               while (port->IER & IER_TXEMPTY) {
                        msleep_interruptible(jiffies_to_msecs(port->timeout));
                        if (time_after(jiffies, timeout))
                                break;
                }
        }
        rc_shutdown_port(bp, port);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       rc_flush_buffer(tty);
        tty_ldisc_flush(tty);
 
        tty->closing = 0;
        port->tty = NULL;
        if (port->blocked_open) {
-               if (port->close_delay) {
+               if (port->close_delay)
                        msleep_interruptible(jiffies_to_msecs(port->close_delay));
-               }
                wake_up_interruptible(&port->open_wait);
        }
        port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
@@ -1097,17 +1095,17 @@ out:
        spin_unlock_irqrestore(&riscom_lock, flags);
 }
 
-static int rc_write(struct tty_struct * tty, 
+static int rc_write(struct tty_struct *tty,
                    const unsigned char *buf, int count)
 {
        struct riscom_port *port = (struct riscom_port *)tty->driver_data;
        struct riscom_board *bp;
        int c, total = 0;
        unsigned long flags;
-                               
+
        if (rc_paranoia_check(port, tty->name, "rc_write"))
                return 0;
-       
+
        bp = port_Board(port);
 
        if (!tty || !port->xmit_buf)
@@ -1144,38 +1142,41 @@ static int rc_write(struct tty_struct * tty,
        return total;
 }
 
-static void rc_put_char(struct tty_struct * tty, unsigned char ch)
+static int rc_put_char(struct tty_struct *tty, unsigned char ch)
 {
        struct riscom_port *port = (struct riscom_port *)tty->driver_data;
        unsigned long flags;
+       int ret = 0;
 
        if (rc_paranoia_check(port, tty->name, "rc_put_char"))
-               return;
+               return 0;
 
        if (!tty || !port->xmit_buf)
-               return;
+               return 0;
 
        spin_lock_irqsave(&riscom_lock, flags);
-       
+
        if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
                goto out;
 
        port->xmit_buf[port->xmit_head++] = ch;
        port->xmit_head &= SERIAL_XMIT_SIZE - 1;
        port->xmit_cnt++;
+       ret = 1;
 
 out:
        spin_unlock_irqrestore(&riscom_lock, flags);
+       return ret;
 }
 
-static void rc_flush_chars(struct tty_struct * tty)
+static void rc_flush_chars(struct tty_struct *tty)
 {
        struct riscom_port *port = (struct riscom_port *)tty->driver_data;
        unsigned long flags;
-                               
+
        if (rc_paranoia_check(port, tty->name, "rc_flush_chars"))
                return;
-       
+
        if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
            !port->xmit_buf)
                return;
@@ -1189,11 +1190,11 @@ static void rc_flush_chars(struct tty_struct * tty)
        spin_unlock_irqrestore(&riscom_lock, flags);
 }
 
-static int rc_write_room(struct tty_struct * tty)
+static int rc_write_room(struct tty_struct *tty)
 {
        struct riscom_port *port = (struct riscom_port *)tty->driver_data;
        int     ret;
-                               
+
        if (rc_paranoia_check(port, tty->name, "rc_write_room"))
                return 0;
 
@@ -1206,39 +1207,22 @@ static int rc_write_room(struct tty_struct * tty)
 static int rc_chars_in_buffer(struct tty_struct *tty)
 {
        struct riscom_port *port = (struct riscom_port *)tty->driver_data;
-                               
+
        if (rc_paranoia_check(port, tty->name, "rc_chars_in_buffer"))
                return 0;
-       
-       return port->xmit_cnt;
-}
-
-static void rc_flush_buffer(struct tty_struct *tty)
-{
-       struct riscom_port *port = (struct riscom_port *)tty->driver_data;
-       unsigned long flags;
-                               
-       if (rc_paranoia_check(port, tty->name, "rc_flush_buffer"))
-               return;
-
-       spin_lock_irqsave(&riscom_lock, flags);
-
-       port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
 
-       spin_unlock_irqrestore(&riscom_lock, flags);
-       
-       tty_wakeup(tty);
+       return port->xmit_cnt;
 }
 
 static int rc_tiocmget(struct tty_struct *tty, struct file *file)
 {
        struct riscom_port *port = (struct riscom_port *)tty->driver_data;
-       struct riscom_board * bp;
+       struct riscom_board *bp;
        unsigned char status;
        unsigned int result;
        unsigned long flags;
 
-       if (rc_paranoia_check(port, tty->name, __FUNCTION__))
+       if (rc_paranoia_check(port, tty->name, __func__))
                return -ENODEV;
 
        bp = port_Board(port);
@@ -1266,7 +1250,7 @@ static int rc_tiocmset(struct tty_struct *tty, struct file *file,
        unsigned long flags;
        struct riscom_board *bp;
 
-       if (rc_paranoia_check(port, tty->name, __FUNCTION__))
+       if (rc_paranoia_check(port, tty->name, __func__))
                return -ENODEV;
 
        bp = port_Board(port);
@@ -1292,11 +1276,11 @@ static int rc_tiocmset(struct tty_struct *tty, struct file *file,
        return 0;
 }
 
-static inline void rc_send_break(struct riscom_port * port, unsigned long length)
+static void rc_send_break(struct riscom_port *port, unsigned long length)
 {
        struct riscom_board *bp = port_Board(port);
        unsigned long flags;
-       
+
        spin_lock_irqsave(&riscom_lock, flags);
 
        port->break_length = RISCOM_TPS / HZ * length;
@@ -1312,17 +1296,17 @@ static inline void rc_send_break(struct riscom_port * port, unsigned long length
        spin_unlock_irqrestore(&riscom_lock, flags);
 }
 
-static inline int rc_set_serial_info(struct riscom_port * port,
-                                    struct serial_struct __user * newinfo)
+static int rc_set_serial_info(struct riscom_port *port,
+                                    struct serial_struct __user *newinfo)
 {
        struct serial_struct tmp;
        struct riscom_board *bp = port_Board(port);
        int change_speed;
-       
+
        if (copy_from_user(&tmp, newinfo, sizeof(tmp)))
                return -EFAULT;
-       
-#if 0  
+
+#if 0
        if ((tmp.irq != bp->irq) ||
            (tmp.port != bp->base) ||
            (tmp.type != PORT_CIRRUS) ||
@@ -1331,16 +1315,16 @@ static inline int rc_set_serial_info(struct riscom_port * port,
            (tmp.xmit_fifo_size != CD180_NFIFO) ||
            (tmp.flags & ~RISCOM_LEGAL_FLAGS))
                return -EINVAL;
-#endif 
-       
+#endif
+
        change_speed = ((port->flags & ASYNC_SPD_MASK) !=
                        (tmp.flags & ASYNC_SPD_MASK));
-       
+
        if (!capable(CAP_SYS_ADMIN)) {
                if ((tmp.close_delay != port->close_delay) ||
                    (tmp.closing_wait != port->closing_wait) ||
                    ((tmp.flags & ~ASYNC_USR_MASK) !=
-                    (port->flags & ~ASYNC_USR_MASK)))  
+                    (port->flags & ~ASYNC_USR_MASK)))
                        return -EPERM;
                port->flags = ((port->flags & ~ASYNC_USR_MASK) |
                               (tmp.flags & ASYNC_USR_MASK));
@@ -1360,12 +1344,12 @@ static inline int rc_set_serial_info(struct riscom_port * port,
        return 0;
 }
 
-static inline int rc_get_serial_info(struct riscom_port * port,
+static int rc_get_serial_info(struct riscom_port *port,
                                     struct serial_struct __user *retinfo)
 {
        struct serial_struct tmp;
        struct riscom_board *bp = port_Board(port);
-       
+
        memset(&tmp, 0, sizeof(tmp));
        tmp.type = PORT_CIRRUS;
        tmp.line = port - rc_port;
@@ -1379,19 +1363,18 @@ static inline int rc_get_serial_info(struct riscom_port * port,
        return copy_to_user(retinfo, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 }
 
-static int rc_ioctl(struct tty_struct * tty, struct file * filp, 
+static int rc_ioctl(struct tty_struct *tty, struct file *filp,
                    unsigned int cmd, unsigned long arg)
-                   
 {
        struct riscom_port *port = (struct riscom_port *)tty->driver_data;
        void __user *argp = (void __user *)arg;
-       int retval;
-                               
+       int retval = 0;
+
        if (rc_paranoia_check(port, tty->name, "rc_ioctl"))
                return -ENODEV;
-       
+
        switch (cmd) {
-        case TCSBRK:   /* SVID version: non-zero arg --> no break */
+       case TCSBRK:    /* SVID version: non-zero arg --> no break */
                retval = tty_check_change(tty);
                if (retval)
                        return retval;
@@ -1399,45 +1382,40 @@ static int rc_ioctl(struct tty_struct * tty, struct file * filp,
                if (!arg)
                        rc_send_break(port, HZ/4);      /* 1/4 second */
                break;
-        case TCSBRKP:  /* support for POSIX tcsendbreak() */
+       case TCSBRKP:   /* support for POSIX tcsendbreak() */
                retval = tty_check_change(tty);
                if (retval)
                        return retval;
                tty_wait_until_sent(tty, 0);
                rc_send_break(port, arg ? arg*(HZ/10) : HZ/4);
                break;
-        case TIOCGSOFTCAR:
-               return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned __user *)argp);
-        case TIOCSSOFTCAR:
-               if (get_user(arg,(unsigned __user *) argp))
-                       return -EFAULT;
-               tty->termios->c_cflag =
-                       ((tty->termios->c_cflag & ~CLOCAL) |
-                       (arg ? CLOCAL : 0));
+       case TIOCGSERIAL:
+               lock_kernel();
+               retval = rc_get_serial_info(port, argp);
+               unlock_kernel();
                break;
-        case TIOCGSERIAL:      
-               return rc_get_serial_info(port, argp);
-        case TIOCSSERIAL:      
-               return rc_set_serial_info(port, argp);
-        default:
-               return -ENOIOCTLCMD;
+       case TIOCSSERIAL:
+               lock_kernel();
+               retval = rc_set_serial_info(port, argp);
+               unlock_kernel();
+               break;
+       default:
+               retval = -ENOIOCTLCMD;
        }
-       return 0;
+       return retval;
 }
 
-static void rc_throttle(struct tty_struct * tty)
+static void rc_throttle(struct tty_struct *tty)
 {
        struct riscom_port *port = (struct riscom_port *)tty->driver_data;
        struct riscom_board *bp;
        unsigned long flags;
-                               
+
        if (rc_paranoia_check(port, tty->name, "rc_throttle"))
                return;
-       
        bp = port_Board(port);
 
        spin_lock_irqsave(&riscom_lock, flags);
-
        port->MSVR &= ~MSVR_RTS;
        rc_out(bp, CD180_CAR, port_No(port));
        if (I_IXOFF(tty)) {
@@ -1446,23 +1424,20 @@ static void rc_throttle(struct tty_struct * tty)
                rc_wait_CCR(bp);
        }
        rc_out(bp, CD180_MSVR, port->MSVR);
-
        spin_unlock_irqrestore(&riscom_lock, flags);
 }
 
-static void rc_unthrottle(struct tty_struct * tty)
+static void rc_unthrottle(struct tty_struct *tty)
 {
        struct riscom_port *port = (struct riscom_port *)tty->driver_data;
        struct riscom_board *bp;
        unsigned long flags;
-                               
+
        if (rc_paranoia_check(port, tty->name, "rc_unthrottle"))
                return;
-       
        bp = port_Board(port);
-       
-       spin_lock_irqsave(&riscom_lock, flags);
 
+       spin_lock_irqsave(&riscom_lock, flags);
        port->MSVR |= MSVR_RTS;
        rc_out(bp, CD180_CAR, port_No(port));
        if (I_IXOFF(tty))  {
@@ -1471,62 +1446,58 @@ static void rc_unthrottle(struct tty_struct * tty)
                rc_wait_CCR(bp);
        }
        rc_out(bp, CD180_MSVR, port->MSVR);
-
        spin_unlock_irqrestore(&riscom_lock, flags);
 }
 
-static void rc_stop(struct tty_struct * tty)
+static void rc_stop(struct tty_struct *tty)
 {
        struct riscom_port *port = (struct riscom_port *)tty->driver_data;
        struct riscom_board *bp;
        unsigned long flags;
-                               
+
        if (rc_paranoia_check(port, tty->name, "rc_stop"))
                return;
-       
+
        bp = port_Board(port);
-       
-       spin_lock_irqsave(&riscom_lock, flags);
 
+       spin_lock_irqsave(&riscom_lock, flags);
        port->IER &= ~IER_TXRDY;
        rc_out(bp, CD180_CAR, port_No(port));
        rc_out(bp, CD180_IER, port->IER);
-
        spin_unlock_irqrestore(&riscom_lock, flags);
 }
 
-static void rc_start(struct tty_struct * tty)
+static void rc_start(struct tty_struct *tty)
 {
        struct riscom_port *port = (struct riscom_port *)tty->driver_data;
        struct riscom_board *bp;
        unsigned long flags;
-                               
+
        if (rc_paranoia_check(port, tty->name, "rc_start"))
                return;
-       
+
        bp = port_Board(port);
-       
+
        spin_lock_irqsave(&riscom_lock, flags);
 
-       if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY))  {
+       if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
                port->IER |= IER_TXRDY;
                rc_out(bp, CD180_CAR, port_No(port));
                rc_out(bp, CD180_IER, port->IER);
        }
-
        spin_unlock_irqrestore(&riscom_lock, flags);
 }
 
-static void rc_hangup(struct tty_struct * tty)
+static void rc_hangup(struct tty_struct *tty)
 {
        struct riscom_port *port = (struct riscom_port *)tty->driver_data;
        struct riscom_board *bp;
-                               
+
        if (rc_paranoia_check(port, tty->name, "rc_hangup"))
                return;
-       
+
        bp = port_Board(port);
-       
+
        rc_shutdown_port(bp, port);
        port->count = 0;
        port->flags &= ~ASYNC_NORMAL_ACTIVE;
@@ -1534,17 +1505,14 @@ static void rc_hangup(struct tty_struct * tty)
        wake_up_interruptible(&port->open_wait);
 }
 
-static void rc_set_termios(struct tty_struct * tty, struct ktermios * old_termios)
+static void rc_set_termios(struct tty_struct *tty,
+                                       struct ktermios *old_termios)
 {
        struct riscom_port *port = (struct riscom_port *)tty->driver_data;
        unsigned long flags;
-                               
+
        if (rc_paranoia_check(port, tty->name, "rc_set_termios"))
                return;
-       
-       if (tty->termios->c_cflag == old_termios->c_cflag &&
-           tty->termios->c_iflag == old_termios->c_iflag)
-               return;
 
        spin_lock_irqsave(&riscom_lock, flags);
        rc_change_speed(port_Board(port), port);
@@ -1583,9 +1551,9 @@ static int __init rc_init_drivers(void)
        int i;
 
        riscom_driver = alloc_tty_driver(RC_NBOARD * RC_NPORT);
-       if (!riscom_driver)     
+       if (!riscom_driver)
                return -ENOMEM;
-       
+
        riscom_driver->owner = THIS_MODULE;
        riscom_driver->name = "ttyL";
        riscom_driver->major = RISCOM8_NORMAL_MAJOR;
@@ -1598,23 +1566,21 @@ static int __init rc_init_drivers(void)
        riscom_driver->init_termios.c_ospeed = 9600;
        riscom_driver->flags = TTY_DRIVER_REAL_RAW;
        tty_set_operations(riscom_driver, &riscom_ops);
-       if ((error = tty_register_driver(riscom_driver)))  {
+       error = tty_register_driver(riscom_driver);
+       if (error != 0) {
                put_tty_driver(riscom_driver);
                printk(KERN_ERR "rc: Couldn't register RISCom/8 driver, "
-                               "error = %d\n",
-                      error);
+                               "error = %d\n", error);
                return 1;
        }
-
        memset(rc_port, 0, sizeof(rc_port));
        for (i = 0; i < RC_NPORT * RC_NBOARD; i++)  {
                rc_port[i].magic = RISCOM8_MAGIC;
-               rc_port[i].close_delay = 50 * HZ/100;
-               rc_port[i].closing_wait = 3000 * HZ/100;
+               rc_port[i].close_delay = 50 * HZ / 100;
+               rc_port[i].closing_wait = 3000 * HZ / 100;
                init_waitqueue_head(&rc_port[i].open_wait);
                init_waitqueue_head(&rc_port[i].close_wait);
        }
-       
        return 0;
 }
 
@@ -1627,13 +1593,13 @@ static void rc_release_drivers(void)
 #ifndef MODULE
 /*
  * Called at boot time.
- * 
+ *
  * You can specify IO base for up to RC_NBOARD cards,
  * using line "riscom8=0xiobase1,0xiobase2,.." at LILO prompt.
  * Note that there will be no probing at default
  * addresses in this case.
  *
- */ 
+ */
 static int __init riscom8_setup(char *str)
 {
        int ints[RC_NBOARD];
@@ -1644,7 +1610,7 @@ static int __init riscom8_setup(char *str)
        for (i = 0; i < RC_NBOARD; i++) {
                if (i < ints[0])
                        rc_board[i].base = ints[i+1];
-               else 
+               else
                        rc_board[i].base = 0;
        }
        return 1;
@@ -1659,8 +1625,8 @@ static char banner[] __initdata =
 static char no_boards_msg[] __initdata =
        KERN_INFO "rc: No RISCom/8 boards detected.\n";
 
-/* 
- * This routine must be called by kernel at boot time 
+/*
+ * This routine must be called by kernel at boot time
  */
 static int __init riscom8_init(void)
 {
@@ -1669,13 +1635,12 @@ static int __init riscom8_init(void)
 
        printk(banner);
 
-       if (rc_init_drivers()) 
+       if (rc_init_drivers())
                return -EIO;
 
-       for (i = 0; i < RC_NBOARD; i++) 
-               if (rc_board[i].base && !rc_probe(&rc_board[i]))  
+       for (i = 0; i < RC_NBOARD; i++)
+               if (rc_board[i].base && !rc_probe(&rc_board[i]))
                        found++;
-       
        if (!found)  {
                rc_release_drivers();
                printk(no_boards_msg);
@@ -1702,13 +1667,13 @@ MODULE_LICENSE("GPL");
  * by specifying "iobase=0xXXX iobase1=0xXXX ..." as insmod parameter.
  *
  */
-static int __init riscom8_init_module (void)
+static int __init riscom8_init_module(void)
 {
 #ifdef MODULE
        int i;
 
        if (iobase || iobase1 || iobase2 || iobase3) {
-               for(i = 0; i < RC_NBOARD; i++)
+               for (i = 0; i < RC_NBOARD; i++)
                        rc_board[i].base = 0;
        }
 
@@ -1724,18 +1689,17 @@ static int __init riscom8_init_module (void)
 
        return riscom8_init();
 }
-       
-static void __exit riscom8_exit_module (void)
+
+static void __exit riscom8_exit_module(void)
 {
        int i;
-       
+
        rc_release_drivers();
-       for (i = 0; i < RC_NBOARD; i++)  
-               if (rc_board[i].flags & RC_BOARD_PRESENT) 
+       for (i = 0; i < RC_NBOARD; i++)
+               if (rc_board[i].flags & RC_BOARD_PRESENT)
                        rc_release_io_range(&rc_board[i]);
-       
+
 }
 
 module_init(riscom8_init_module);
 module_exit(riscom8_exit_module);
-
index f585bc8579e9929aba1e6f6d35b00991844e0f39..743dc80a9325bd806476fe9e91fb72d46297d27e 100644 (file)
@@ -449,7 +449,8 @@ static void rp_do_transmit(struct r_port *info)
        while (1) {
                if (tty->stopped || tty->hw_stopped)
                        break;
-               c = min(info->xmit_fifo_room, min(info->xmit_cnt, XMIT_BUF_SIZE - info->xmit_tail));
+               c = min(info->xmit_fifo_room, info->xmit_cnt);
+               c = min(c, XMIT_BUF_SIZE - info->xmit_tail);
                if (c <= 0 || info->xmit_fifo_room <= 0)
                        break;
                sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) (info->xmit_buf + info->xmit_tail), c / 2);
@@ -1433,29 +1434,38 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file,
 {
        struct r_port *info = (struct r_port *) tty->driver_data;
        void __user *argp = (void __user *)arg;
+       int ret = 0;
 
        if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl"))
                return -ENXIO;
 
+       lock_kernel();
+
        switch (cmd) {
        case RCKP_GET_STRUCT:
                if (copy_to_user(argp, info, sizeof (struct r_port)))
-                       return -EFAULT;
-               return 0;
+                       ret = -EFAULT;
+               break;
        case RCKP_GET_CONFIG:
-               return get_config(info, argp);
+               ret = get_config(info, argp);
+               break;
        case RCKP_SET_CONFIG:
-               return set_config(info, argp);
+               ret = set_config(info, argp);
+               break;
        case RCKP_GET_PORTS:
-               return get_ports(info, argp);
+               ret = get_ports(info, argp);
+               break;
        case RCKP_RESET_RM2:
-               return reset_rm2(info, argp);
+               ret = reset_rm2(info, argp);
+               break;
        case RCKP_GET_VERSION:
-               return get_version(info, argp);
+               ret = get_version(info, argp);
+               break;
        default:
-               return -ENOIOCTLCMD;
+               ret = -ENOIOCTLCMD;
        }
-       return 0;
+       unlock_kernel();
+       return ret;
 }
 
 static void rp_send_xchar(struct tty_struct *tty, char ch)
@@ -1575,6 +1585,7 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
               jiffies);
        printk(KERN_INFO "cps=%d...\n", info->cps);
 #endif
+       lock_kernel();
        while (1) {
                txcnt = sGetTxCnt(cp);
                if (!txcnt) {
@@ -1602,6 +1613,7 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
                        break;
        }
        __set_current_state(TASK_RUNNING);
+       unlock_kernel();
 #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
        printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies);
 #endif
@@ -1651,14 +1663,14 @@ static void rp_hangup(struct tty_struct *tty)
  *  writing routines will write directly to transmit FIFO.
  *  Write buffer and counters protected by spinlocks
  */
-static void rp_put_char(struct tty_struct *tty, unsigned char ch)
+static int rp_put_char(struct tty_struct *tty, unsigned char ch)
 {
        struct r_port *info = (struct r_port *) tty->driver_data;
        CHANNEL_t *cp;
        unsigned long flags;
 
        if (rocket_paranoia_check(info, "rp_put_char"))
-               return;
+               return 0;
 
        /*
         * Grab the port write mutex, locking out other processes that try to
@@ -1687,6 +1699,7 @@ static void rp_put_char(struct tty_struct *tty, unsigned char ch)
        }
        spin_unlock_irqrestore(&info->slock, flags);
        mutex_unlock(&info->write_mtx);
+       return 1;
 }
 
 /*
@@ -1749,10 +1762,10 @@ static int rp_write(struct tty_struct *tty,
 
        /*  Write remaining data into the port's xmit_buf */
        while (1) {
-               if (!info->tty) /*   Seemingly obligatory check... */
+               if (!info->tty)         /* Seemingly obligatory check... */
                        goto end;
-
-               c = min(count, min(XMIT_BUF_SIZE - info->xmit_cnt - 1, XMIT_BUF_SIZE - info->xmit_head));
+               c = min(count, XMIT_BUF_SIZE - info->xmit_cnt - 1);
+               c = min(c, XMIT_BUF_SIZE - info->xmit_head);
                if (c <= 0)
                        break;
 
index b01d38125a8f1f575ec0cb5131e86636746bebd8..143cc432fdb2bec3cb0bbdb1be0188e3cc034765 100644 (file)
@@ -55,7 +55,7 @@ static inline void sOutW(unsigned short port, unsigned short value)
 
 static inline void out32(unsigned short port, Byte_t *p)
 {
-       u32 value = le32_to_cpu(get_unaligned((__le32 *)p));
+       u32 value = get_unaligned_le32(p);
 #ifdef ROCKET_DEBUG_IO
        printk(KERN_DEBUG "out32(%x, %lx)...\n", port, value);
 #endif
index e2ec2ee4cf79dc4e5f30b1add1d52ecf5f418f77..5f80a9dff5735103b91cc16c40338aafa96f853a 100644 (file)
@@ -1069,10 +1069,8 @@ no_irq:
        }
 
 #ifdef CONFIG_PROC_FS
-       ent = create_proc_entry("driver/rtc", 0, NULL);
-       if (ent)
-               ent->proc_fops = &rtc_proc_fops;
-       else
+       ent = proc_create("driver/rtc", 0, NULL, &rtc_proc_fops);
+       if (!ent)
                printk(KERN_WARNING "rtc: Failed to register with procfs.\n");
 #endif
 
index df8cd0ca97ebcc5d8728ab36ffcdeabcd899c4f3..fd2db07a50fce9bf39e2bcaf0060bc7fc71f8a09 100644 (file)
@@ -1060,7 +1060,7 @@ static void config_setup(struct cyclades_port *info)
 
 }                              /* config_setup */
 
-static void cy_put_char(struct tty_struct *tty, unsigned char ch)
+static int cy_put_char(struct tty_struct *tty, unsigned char ch)
 {
        struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
        unsigned long flags;
@@ -1070,7 +1070,7 @@ static void cy_put_char(struct tty_struct *tty, unsigned char ch)
 #endif
 
        if (serial_paranoia_check(info, tty->name, "cy_put_char"))
-               return;
+               return 0;
 
        if (!info->xmit_buf)
                return;
@@ -1078,13 +1078,14 @@ static void cy_put_char(struct tty_struct *tty, unsigned char ch)
        local_irq_save(flags);
        if (info->xmit_cnt >= PAGE_SIZE - 1) {
                local_irq_restore(flags);
-               return;
+               return 0;
        }
 
        info->xmit_buf[info->xmit_head++] = ch;
        info->xmit_head &= PAGE_SIZE - 1;
        info->xmit_cnt++;
        local_irq_restore(flags);
+       return 1;
 }                              /* cy_put_char */
 
 static void cy_flush_chars(struct tty_struct *tty)
@@ -1539,6 +1540,8 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
        printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg);       /* */
 #endif
 
+       lock_kernel();
+
        switch (cmd) {
        case CYGETMON:
                ret_val = get_mon_info(info, argp);
@@ -1584,18 +1587,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
                break;
 
 /* The following commands are incompletely implemented!!! */
-       case TIOCGSOFTCAR:
-               ret_val =
-                   put_user(C_CLOCAL(tty) ? 1 : 0,
-                            (unsigned long __user *)argp);
-               break;
-       case TIOCSSOFTCAR:
-               ret_val = get_user(val, (unsigned long __user *)argp);
-               if (ret_val)
-                       break;
-               tty->termios->c_cflag =
-                   ((tty->termios->c_cflag & ~CLOCAL) | (val ? CLOCAL : 0));
-               break;
        case TIOCGSERIAL:
                ret_val = get_serial_info(info, argp);
                break;
@@ -1605,6 +1596,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
        default:
                ret_val = -ENOIOCTLCMD;
        }
+       unlock_kernel();
 
 #ifdef SERIAL_DEBUG_OTHER
        printk("cy_ioctl done\n");
@@ -1683,8 +1675,7 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
        if (info->flags & ASYNC_INITIALIZED)
                tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
        shutdown(info);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       cy_flush_buffer(tty);
        tty_ldisc_flush(tty);
        info->tty = NULL;
        if (info->blocked_open) {
index b9c1dba6bd01fe2882f404d90b2bd745872b50e9..8fe099a410654ffb35c5e9c0a3e8c42c8acbcb59 100644 (file)
@@ -80,7 +80,7 @@ scdrv_open(struct inode *inode, struct file *file)
        sd = kzalloc(sizeof (struct subch_data_s), GFP_KERNEL);
        if (sd == NULL) {
                printk("%s: couldn't allocate subchannel data\n",
-                      __FUNCTION__);
+                      __func__);
                return -ENOMEM;
        }
 
@@ -90,7 +90,7 @@ scdrv_open(struct inode *inode, struct file *file)
 
        if (sd->sd_subch < 0) {
                kfree(sd);
-               printk("%s: couldn't allocate subchannel\n", __FUNCTION__);
+               printk("%s: couldn't allocate subchannel\n", __func__);
                return -EBUSY;
        }
 
@@ -110,7 +110,7 @@ scdrv_open(struct inode *inode, struct file *file)
        if (rv) {
                ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch);
                kfree(sd);
-               printk("%s: irq request failed (%d)\n", __FUNCTION__, rv);
+               printk("%s: irq request failed (%d)\n", __func__, rv);
                return -EBUSY;
        }
 
@@ -215,7 +215,7 @@ scdrv_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos)
                 */
                if (count < len) {
                        pr_debug("%s: only accepting %d of %d bytes\n",
-                                __FUNCTION__, (int) count, len);
+                                __func__, (int) count, len);
                }
                len = min((int) count, len);
                if (copy_to_user(buf, sd->sd_rb, len))
@@ -384,7 +384,7 @@ scdrv_init(void)
        if (alloc_chrdev_region(&first_dev, 0, num_cnodes,
                                SYSCTL_BASENAME) < 0) {
                printk("%s: failed to register SN system controller device\n",
-                      __FUNCTION__);
+                      __func__);
                return -ENODEV;
        }
        snsc_class = class_create(THIS_MODULE, SYSCTL_BASENAME);
@@ -403,7 +403,7 @@ scdrv_init(void)
                                      GFP_KERNEL);
                        if (!scd) {
                                printk("%s: failed to allocate device info"
-                                      "for %s/%s\n", __FUNCTION__,
+                                      "for %s/%s\n", __func__,
                                       SYSCTL_BASENAME, devname);
                                continue;
                        }
@@ -412,7 +412,7 @@ scdrv_init(void)
                        scd->scd_nasid = cnodeid_to_nasid(cnode);
                        if (!(salbuf = kmalloc(SCDRV_BUFSZ, GFP_KERNEL))) {
                                printk("%s: failed to allocate driver buffer"
-                                      "(%s%s)\n", __FUNCTION__,
+                                      "(%s%s)\n", __func__,
                                       SYSCTL_BASENAME, devname);
                                kfree(scd);
                                continue;
@@ -424,7 +424,7 @@ scdrv_init(void)
                                    ("%s: failed to initialize SAL for"
                                     " system controller communication"
                                     " (%s/%s): outdated PROM?\n",
-                                    __FUNCTION__, SYSCTL_BASENAME, devname);
+                                    __func__, SYSCTL_BASENAME, devname);
                                kfree(scd);
                                kfree(salbuf);
                                continue;
@@ -435,7 +435,7 @@ scdrv_init(void)
                        if (cdev_add(&scd->scd_cdev, dev, 1)) {
                                printk("%s: failed to register system"
                                       " controller device (%s%s)\n",
-                                      __FUNCTION__, SYSCTL_BASENAME, devname);
+                                      __func__, SYSCTL_BASENAME, devname);
                                kfree(scd);
                                kfree(salbuf);
                                continue;
index 1b75b0b7d5429dae92918dc1987c813b1de25138..53b3d44f8c066bb06dfa84e6ac98a7ddff660628 100644 (file)
@@ -63,16 +63,13 @@ static int
 scdrv_parse_event(char *event, int *src, int *code, int *esp_code, char *desc)
 {
        char *desc_end;
-       __be32 from_buf;
 
        /* record event source address */
-       from_buf = get_unaligned((__be32 *)event);
-       *src = be32_to_cpup(&from_buf);
+       *src = get_unaligned_be32(event);
        event += 4;                     /* move on to event code */
 
        /* record the system controller's event code */
-       from_buf = get_unaligned((__be32 *)event);
-       *code = be32_to_cpup(&from_buf);
+       *code = get_unaligned_be32(event);
        event += 4;                     /* move on to event arguments */
 
        /* how many arguments are in the packet? */
@@ -86,8 +83,7 @@ scdrv_parse_event(char *event, int *src, int *code, int *esp_code, char *desc)
                /* not an integer argument, so give up */
                return -1;
        }
-       from_buf = get_unaligned((__be32 *)event);
-       *esp_code = be32_to_cpup(&from_buf);
+       *esp_code = get_unaligned_be32(event);
        event += 4;
 
        /* parse out the event description */
@@ -275,7 +271,7 @@ scdrv_event_init(struct sysctl_data_s *scd)
        event_sd = kzalloc(sizeof (struct subch_data_s), GFP_KERNEL);
        if (event_sd == NULL) {
                printk(KERN_WARNING "%s: couldn't allocate subchannel info"
-                      " for event monitoring\n", __FUNCTION__);
+                      " for event monitoring\n", __func__);
                return;
        }
 
@@ -289,7 +285,7 @@ scdrv_event_init(struct sysctl_data_s *scd)
        if (event_sd->sd_subch < 0) {
                kfree(event_sd);
                printk(KERN_WARNING "%s: couldn't open event subchannel\n",
-                      __FUNCTION__);
+                      __func__);
                return;
        }
 
@@ -299,7 +295,7 @@ scdrv_event_init(struct sysctl_data_s *scd)
                         "system controller events", event_sd);
        if (rv) {
                printk(KERN_WARNING "%s: irq request failed (%d)\n",
-                      __FUNCTION__, rv);
+                      __func__, rv);
                ia64_sn_irtr_close(event_sd->sd_nasid, event_sd->sd_subch);
                kfree(event_sd);
                return;
index c03ad164c39af5ff1e7fd73c7858c5f5ff9ab2f2..58533de59027806360ffe816e5b5571becf966b8 100644 (file)
@@ -506,7 +506,7 @@ static struct sonypi_device {
        while (--n && (command)) \
                udelay(1); \
        if (!n && (verbose || !quiet)) \
-               printk(KERN_WARNING "sonypi command failed at %s : %s (line %d)\n", __FILE__, __FUNCTION__, __LINE__); \
+               printk(KERN_WARNING "sonypi command failed at %s : %s (line %d)\n", __FILE__, __func__, __LINE__); \
 }
 
 #ifdef CONFIG_ACPI
index 4b5b5b78acb4835c3e58a212b92c87d035e512c5..2ee4d98937572195b474b5efdd42666606520a7a 100644 (file)
@@ -131,8 +131,8 @@ static int sx_rxfifo = SPECIALIX_RXFIFO;
 #define SX_DEBUG_FIFO    0x0800
 
 
-#define func_enter() dprintk (SX_DEBUG_FLOW, "io8: enter %s\n",__FUNCTION__)
-#define func_exit()  dprintk (SX_DEBUG_FLOW, "io8: exit  %s\n", __FUNCTION__)
+#define func_enter() dprintk (SX_DEBUG_FLOW, "io8: enter %s\n",__func__)
+#define func_exit()  dprintk (SX_DEBUG_FLOW, "io8: exit  %s\n", __func__)
 
 #define jiffies_from_ms(a) ((((a) * HZ)/1000)+1)
 
@@ -874,7 +874,7 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id)
 
        spin_lock_irqsave(&bp->lock, flags);
 
-       dprintk (SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __FUNCTION__, port_No(sx_get_port(bp, "INT")), SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1);
+       dprintk (SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__, port_No(sx_get_port(bp, "INT")), SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1);
        if (!(bp->flags & SX_BOARD_ACTIVE)) {
                dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", bp->irq);
                spin_unlock_irqrestore(&bp->lock, flags);
@@ -1504,6 +1504,27 @@ static int sx_open(struct tty_struct * tty, struct file * filp)
        return 0;
 }
 
+static void sx_flush_buffer(struct tty_struct *tty)
+{
+       struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+       unsigned long flags;
+       struct specialix_board  * bp;
+
+       func_enter();
+
+       if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) {
+               func_exit();
+               return;
+       }
+
+       bp = port_Board(port);
+       spin_lock_irqsave(&port->lock, flags);
+       port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+       spin_unlock_irqrestore(&port->lock, flags);
+       tty_wakeup(tty);
+
+       func_exit();
+}
 
 static void sx_close(struct tty_struct * tty, struct file * filp)
 {
@@ -1597,8 +1618,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
        }
 
        sx_shutdown_port(bp, port);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       sx_flush_buffer(tty);
        tty_ldisc_flush(tty);
        spin_lock_irqsave(&port->lock, flags);
        tty->closing = 0;
@@ -1670,7 +1690,7 @@ static int sx_write(struct tty_struct * tty,
 }
 
 
-static void sx_put_char(struct tty_struct * tty, unsigned char ch)
+static int sx_put_char(struct tty_struct * tty, unsigned char ch)
 {
        struct specialix_port *port = (struct specialix_port *)tty->driver_data;
        unsigned long flags;
@@ -1680,12 +1700,12 @@ static void sx_put_char(struct tty_struct * tty, unsigned char ch)
 
        if (sx_paranoia_check(port, tty->name, "sx_put_char")) {
                func_exit();
-               return;
+               return 0;
        }
        dprintk (SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
        if (!port->xmit_buf) {
                func_exit();
-               return;
+               return 0;
        }
        bp = port_Board(port);
        spin_lock_irqsave(&port->lock, flags);
@@ -1695,7 +1715,7 @@ static void sx_put_char(struct tty_struct * tty, unsigned char ch)
                spin_unlock_irqrestore(&port->lock, flags);
                dprintk (SX_DEBUG_TX, "Exit size\n");
                func_exit();
-               return;
+               return 0;
        }
        dprintk (SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf);
        port->xmit_buf[port->xmit_head++] = ch;
@@ -1704,6 +1724,7 @@ static void sx_put_char(struct tty_struct * tty, unsigned char ch)
        spin_unlock_irqrestore(&port->lock, flags);
 
        func_exit();
+       return 1;
 }
 
 
@@ -1770,28 +1791,6 @@ static int sx_chars_in_buffer(struct tty_struct *tty)
 }
 
 
-static void sx_flush_buffer(struct tty_struct *tty)
-{
-       struct specialix_port *port = (struct specialix_port *)tty->driver_data;
-       unsigned long flags;
-       struct specialix_board  * bp;
-
-       func_enter();
-
-       if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) {
-               func_exit();
-               return;
-       }
-
-       bp = port_Board(port);
-       spin_lock_irqsave(&port->lock, flags);
-       port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-       spin_unlock_irqrestore(&port->lock, flags);
-       tty_wakeup(tty);
-
-       func_exit();
-}
-
 
 static int sx_tiocmget(struct tty_struct *tty, struct file *file)
 {
@@ -1803,7 +1802,7 @@ static int sx_tiocmget(struct tty_struct *tty, struct file *file)
 
        func_enter();
 
-       if (sx_paranoia_check(port, tty->name, __FUNCTION__)) {
+       if (sx_paranoia_check(port, tty->name, __func__)) {
                func_exit();
                return -ENODEV;
        }
@@ -1845,7 +1844,7 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file,
 
        func_enter();
 
-       if (sx_paranoia_check(port, tty->name, __FUNCTION__)) {
+       if (sx_paranoia_check(port, tty->name, __func__)) {
                func_exit();
                return -ENODEV;
        }
@@ -1922,29 +1921,13 @@ static inline int sx_set_serial_info(struct specialix_port * port,
        int change_speed;
 
        func_enter();
-       /*
-       if (!access_ok(VERIFY_READ, (void *) newinfo, sizeof(tmp))) {
-               func_exit();
-               return -EFAULT;
-       }
-       */
+
        if (copy_from_user(&tmp, newinfo, sizeof(tmp))) {
                func_enter();
                return -EFAULT;
        }
 
-#if 0
-       if ((tmp.irq != bp->irq) ||
-           (tmp.port != bp->base) ||
-           (tmp.type != PORT_CIRRUS) ||
-           (tmp.baud_base != (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC) ||
-           (tmp.custom_divisor != 0) ||
-           (tmp.xmit_fifo_size != CD186x_NFIFO) ||
-           (tmp.flags & ~SPECIALIX_LEGAL_FLAGS)) {
-               func_exit();
-               return -EINVAL;
-       }
-#endif
+       lock_kernel();
 
        change_speed = ((port->flags & ASYNC_SPD_MASK) !=
                        (tmp.flags & ASYNC_SPD_MASK));
@@ -1956,6 +1939,7 @@ static inline int sx_set_serial_info(struct specialix_port * port,
                    ((tmp.flags & ~ASYNC_USR_MASK) !=
                     (port->flags & ~ASYNC_USR_MASK))) {
                        func_exit();
+                       unlock_kernel();
                        return -EPERM;
                }
                port->flags = ((port->flags & ~ASYNC_USR_MASK) |
@@ -1972,6 +1956,7 @@ static inline int sx_set_serial_info(struct specialix_port * port,
                sx_change_speed(bp, port);
        }
        func_exit();
+       unlock_kernel();
        return 0;
 }
 
@@ -1984,12 +1969,8 @@ static inline int sx_get_serial_info(struct specialix_port * port,
 
        func_enter();
 
-       /*
-       if (!access_ok(VERIFY_WRITE, (void *) retinfo, sizeof(tmp)))
-               return -EFAULT;
-       */
-
        memset(&tmp, 0, sizeof(tmp));
+       lock_kernel();
        tmp.type = PORT_CIRRUS;
        tmp.line = port - sx_port;
        tmp.port = bp->base;
@@ -2000,6 +1981,7 @@ static inline int sx_get_serial_info(struct specialix_port * port,
        tmp.closing_wait = port->closing_wait * HZ/100;
        tmp.custom_divisor =  port->custom_divisor;
        tmp.xmit_fifo_size = CD186x_NFIFO;
+       unlock_kernel();
        if (copy_to_user(retinfo, &tmp, sizeof(tmp))) {
                func_exit();
                return -EFAULT;
@@ -2045,23 +2027,6 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp,
                sx_send_break(port, arg ? arg*(HZ/10) : HZ/4);
                func_exit();
                return 0;
-        case TIOCGSOFTCAR:
-                if (put_user(C_CLOCAL(tty)?1:0, (unsigned long __user *)argp)) {
-                        func_exit();
-                        return -EFAULT;
-                }
-                func_exit();
-               return 0;
-        case TIOCSSOFTCAR:
-                if (get_user(arg, (unsigned long __user *) argp)) {
-                        func_exit();
-                        return -EFAULT;
-                }
-               tty->termios->c_cflag =
-                       ((tty->termios->c_cflag & ~CLOCAL) |
-                       (arg ? CLOCAL : 0));
-               func_exit();
-               return 0;
         case TIOCGSERIAL:
                 func_exit();
                return sx_get_serial_info(port, argp);
index 874aaa08e956d8ae8143308b9582317076dfd371..d17be10c5d2108f436a1479f15eb1f83373d82f4 100644 (file)
@@ -875,6 +875,7 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)
                timeout = HZ;
        tend = jiffies + timeout;
 
+       lock_kernel();
        while (stl_datastate(portp)) {
                if (signal_pending(current))
                        break;
@@ -882,6 +883,7 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)
                if (time_after_eq(jiffies, tend))
                        break;
        }
+       unlock_kernel();
 }
 
 /*****************************************************************************/
@@ -1273,18 +1275,9 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
 
        rc = 0;
 
+       lock_kernel();
+
        switch (cmd) {
-       case TIOCGSOFTCAR:
-               rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
-                       (unsigned __user *) argp);
-               break;
-       case TIOCSSOFTCAR:
-               if (get_user(ival, (unsigned int __user *) arg))
-                       return -EFAULT;
-               tty->termios->c_cflag =
-                               (tty->termios->c_cflag & ~CLOCAL) |
-                               (ival ? CLOCAL : 0);
-               break;
        case TIOCGSERIAL:
                rc = stl_getserial(portp, argp);
                break;
@@ -1308,7 +1301,7 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
                rc = -ENOIOCTLCMD;
                break;
        }
-
+       unlock_kernel();
        return rc;
 }
 
index a6e1c9ba12174d769e1389d5329b70676e5e3b16..f39f6fd8935064f01af2b91115e70111ddaa6769 100644 (file)
@@ -384,11 +384,11 @@ static struct real_driver sx_real_driver = {
 #define sx_dprintk(f, str...)  /* nothing */
 #endif
 
-#define func_enter()   sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s\n",__FUNCTION__)
-#define func_exit()    sx_dprintk(SX_DEBUG_FLOW, "sx: exit  %s\n",__FUNCTION__)
+#define func_enter()   sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s\n",__func__)
+#define func_exit()    sx_dprintk(SX_DEBUG_FLOW, "sx: exit  %s\n",__func__)
 
 #define func_enter2()  sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \
-                               __FUNCTION__, port->line)
+                               __func__, port->line)
 
 /* 
  *  Firmware loader driver specific routines
@@ -1574,7 +1574,7 @@ static void sx_close(void *ptr)
                sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n",
                                port->gs.count);
                /*printk("%s SETTING port count to zero: %p count: %d\n",
-                               __FUNCTION__, port, port->gs.count);
+                               __func__, port, port->gs.count);
                port->gs.count = 0;*/
        }
 
@@ -1844,6 +1844,7 @@ static void sx_break(struct tty_struct *tty, int flag)
        int rv;
 
        func_enter();
+       lock_kernel();
 
        if (flag)
                rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK);
@@ -1852,7 +1853,7 @@ static void sx_break(struct tty_struct *tty, int flag)
        if (rv != 1)
                printk(KERN_ERR "sx: couldn't send break (%x).\n",
                        read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
-
+       unlock_kernel();
        func_exit();
 }
 
@@ -1888,23 +1889,12 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp,
        int rc;
        struct sx_port *port = tty->driver_data;
        void __user *argp = (void __user *)arg;
-       int ival;
 
        /* func_enter2(); */
 
        rc = 0;
+       lock_kernel();
        switch (cmd) {
-       case TIOCGSOFTCAR:
-               rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),
-                               (unsigned __user *)argp);
-               break;
-       case TIOCSSOFTCAR:
-               if ((rc = get_user(ival, (unsigned __user *)argp)) == 0) {
-                       tty->termios->c_cflag =
-                               (tty->termios->c_cflag & ~CLOCAL) |
-                               (ival ? CLOCAL : 0);
-               }
-               break;
        case TIOCGSERIAL:
                rc = gs_getserial(&port->gs, argp);
                break;
@@ -1915,6 +1905,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp,
                rc = -ENOIOCTLCMD;
                break;
        }
+       unlock_kernel();
 
        /* func_exit(); */
        return rc;
@@ -2549,7 +2540,7 @@ static int __devinit sx_eisa_probe(struct device *dev)
                goto err_flag;
        }
        board->base2 =
-       board->base = ioremap(board->hw_base, SI2_EISA_WINDOW_LEN);
+       board->base = ioremap_nocache(board->hw_base, SI2_EISA_WINDOW_LEN);
        if (!board->base) {
                dev_err(dev, "can't remap memory\n");
                goto err_reg;
@@ -2626,7 +2617,7 @@ static void __devinit fix_sx_pci(struct pci_dev *pdev, struct sx_board *board)
 
        pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
        hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
-       rebase = ioremap(hwbase, 0x80);
+       rebase = ioremap_nocache(hwbase, 0x80);
        t = readl(rebase + CNTRL_REG_OFFSET);
        if (t != CNTRL_REG_GOODVALUE) {
                printk(KERN_DEBUG "sx: performing cntrl reg fix: %08x -> "
@@ -2770,7 +2761,7 @@ static int __init sx_init(void)
                if (!request_region(board->hw_base, board->hw_len, "sx"))
                        continue;
                board->base2 =
-               board->base = ioremap(board->hw_base, board->hw_len);
+               board->base = ioremap_nocache(board->hw_base, board->hw_len);
                if (!board->base)
                        goto err_sx_reg;
                board->flags &= ~SX_BOARD_TYPE;
@@ -2794,7 +2785,7 @@ err_sx_reg:
                if (!request_region(board->hw_base, board->hw_len, "sx"))
                        continue;
                board->base2 =
-               board->base = ioremap(board->hw_base, board->hw_len);
+               board->base = ioremap_nocache(board->hw_base, board->hw_len);
                if (!board->base)
                        goto err_si_reg;
                board->flags &= ~SX_BOARD_TYPE;
@@ -2817,7 +2808,7 @@ err_si_reg:
                if (!request_region(board->hw_base, board->hw_len, "sx"))
                        continue;
                board->base2 =
-               board->base = ioremap(board->hw_base, board->hw_len);
+               board->base = ioremap_nocache(board->hw_base, board->hw_len);
                if (!board->base)
                        goto err_si1_reg;
                board->flags &= ~SX_BOARD_TYPE;
index fadab1d9510fe513a49ac038763da0464b8f1fa0..513b7c2f3e264fc2dd809c7865ebd4b0dd66ee53 100644 (file)
@@ -2026,10 +2026,11 @@ static void mgsl_change_params(struct mgsl_struct *info)
  *             
  * Return Value:       None
  */
-static void mgsl_put_char(struct tty_struct *tty, unsigned char ch)
+static int mgsl_put_char(struct tty_struct *tty, unsigned char ch)
 {
        struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;
        unsigned long flags;
+       int ret;
 
        if ( debug_level >= DEBUG_LEVEL_INFO ) {
                printk( "%s(%d):mgsl_put_char(%d) on %s\n",
@@ -2037,23 +2038,23 @@ static void mgsl_put_char(struct tty_struct *tty, unsigned char ch)
        }               
        
        if (mgsl_paranoia_check(info, tty->name, "mgsl_put_char"))
-               return;
+               return 0;
 
        if (!tty || !info->xmit_buf)
-               return;
+               return 0;
 
        spin_lock_irqsave(&info->irq_spinlock,flags);
        
        if ( (info->params.mode == MGSL_MODE_ASYNC ) || !info->tx_active ) {
-       
                if (info->xmit_cnt < SERIAL_XMIT_SIZE - 1) {
                        info->xmit_buf[info->xmit_head++] = ch;
                        info->xmit_head &= SERIAL_XMIT_SIZE-1;
                        info->xmit_cnt++;
+                       ret = 1;
                }
        }
-       
        spin_unlock_irqrestore(&info->irq_spinlock,flags);
+       return ret;
        
 }      /* end of mgsl_put_char() */
 
@@ -2942,6 +2943,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
                    unsigned int cmd, unsigned long arg)
 {
        struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data;
+       int ret;
        
        if (debug_level >= DEBUG_LEVEL_INFO)
                printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
@@ -2956,7 +2958,10 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
                    return -EIO;
        }
 
-       return mgsl_ioctl_common(info, cmd, arg);
+       lock_kernel();
+       ret = mgsl_ioctl_common(info, cmd, arg);
+       unlock_kernel();
+       return ret;
 }
 
 static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
@@ -3153,8 +3158,7 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp)
        if (info->flags & ASYNC_INITIALIZED)
                mgsl_wait_until_sent(tty, info->timeout);
 
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       mgsl_flush_buffer(tty);
 
        tty_ldisc_flush(tty);
                
@@ -3217,7 +3221,8 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout)
         * interval should also be less than the timeout.
         * Note: use tight timings here to satisfy the NIST-PCTS.
         */ 
-       
+
+       lock_kernel();
        if ( info->params.data_rate ) {
                char_time = info->timeout/(32 * 5);
                if (!char_time)
@@ -3247,6 +3252,7 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout)
                                break;
                }
        }
+       unlock_kernel();
       
 exit:
        if (debug_level >= DEBUG_LEVEL_INFO)
@@ -4144,7 +4150,8 @@ static int mgsl_claim_resources(struct mgsl_struct *info)
                }
                info->lcr_mem_requested = true;
 
-               info->memory_base = ioremap(info->phys_memory_base,0x40000);
+               info->memory_base = ioremap_nocache(info->phys_memory_base,
+                                                               0x40000);
                if (!info->memory_base) {
                        printk( "%s(%d):Cant map shared memory on device %s MemAddr=%08X\n",
                                __FILE__,__LINE__,info->device_name, info->phys_memory_base );
@@ -4157,12 +4164,14 @@ static int mgsl_claim_resources(struct mgsl_struct *info)
                        goto errout;
                }
                
-               info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE) + info->lcr_offset;
+               info->lcr_base = ioremap_nocache(info->phys_lcr_base,
+                                                               PAGE_SIZE);
                if (!info->lcr_base) {
                        printk( "%s(%d):Cant map LCR memory on device %s MemAddr=%08X\n",
                                __FILE__,__LINE__,info->device_name, info->phys_lcr_base );
                        goto errout;
                }
+               info->lcr_base += info->lcr_offset;
                
        } else {
                /* claim DMA channel */
index f3d8d72e5ea47d74e97d1f60a6b68d44b491a01d..2001b0e52dc69c51a765ff8ffdef2a426e202b01 100644 (file)
@@ -151,7 +151,7 @@ static void hangup(struct tty_struct *tty);
 static void set_termios(struct tty_struct *tty, struct ktermios *old_termios);
 
 static int  write(struct tty_struct *tty, const unsigned char *buf, int count);
-static void put_char(struct tty_struct *tty, unsigned char ch);
+static int put_char(struct tty_struct *tty, unsigned char ch);
 static void send_xchar(struct tty_struct *tty, char ch);
 static void wait_until_sent(struct tty_struct *tty, int timeout);
 static int  write_room(struct tty_struct *tty);
@@ -771,8 +771,7 @@ static void close(struct tty_struct *tty, struct file *filp)
 
        if (info->flags & ASYNC_INITIALIZED)
                wait_until_sent(tty, info->timeout);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       flush_buffer(tty);
        tty_ldisc_flush(tty);
 
        shutdown(info);
@@ -913,20 +912,24 @@ cleanup:
        return ret;
 }
 
-static void put_char(struct tty_struct *tty, unsigned char ch)
+static int put_char(struct tty_struct *tty, unsigned char ch)
 {
        struct slgt_info *info = tty->driver_data;
        unsigned long flags;
+       int ret;
 
        if (sanity_check(info, tty->name, "put_char"))
-               return;
+               return 0;
        DBGINFO(("%s put_char(%d)\n", info->device_name, ch));
        if (!info->tx_buf)
-               return;
+               return 0;
        spin_lock_irqsave(&info->lock,flags);
-       if (!info->tx_active && (info->tx_count < info->max_frame_size))
+       if (!info->tx_active && (info->tx_count < info->max_frame_size)) {
                info->tx_buf[info->tx_count++] = ch;
+               ret = 1;
+       }
        spin_unlock_irqrestore(&info->lock,flags);
+       return ret;
 }
 
 static void send_xchar(struct tty_struct *tty, char ch)
@@ -967,6 +970,8 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
         * Note: use tight timings here to satisfy the NIST-PCTS.
         */
 
+       lock_kernel();
+
        if (info->params.data_rate) {
                char_time = info->timeout/(32 * 5);
                if (!char_time)
@@ -984,6 +989,7 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
                if (timeout && time_after(jiffies, orig_jiffies + timeout))
                        break;
        }
+       unlock_kernel();
 
 exit:
        DBGINFO(("%s wait_until_sent exit\n", info->device_name));
@@ -1097,6 +1103,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
        struct serial_icounter_struct __user *p_cuser;  /* user space */
        unsigned long flags;
        void __user *argp = (void __user *)arg;
+       int ret;
 
        if (sanity_check(info, tty->name, "ioctl"))
                return -ENODEV;
@@ -1108,37 +1115,54 @@ static int ioctl(struct tty_struct *tty, struct file *file,
                    return -EIO;
        }
 
+       lock_kernel();
+
        switch (cmd) {
        case MGSL_IOCGPARAMS:
-               return get_params(info, argp);
+               ret = get_params(info, argp);
+               break;
        case MGSL_IOCSPARAMS:
-               return set_params(info, argp);
+               ret = set_params(info, argp);
+               break;
        case MGSL_IOCGTXIDLE:
-               return get_txidle(info, argp);
+               ret = get_txidle(info, argp);
+               break;
        case MGSL_IOCSTXIDLE:
-               return set_txidle(info, (int)arg);
+               ret = set_txidle(info, (int)arg);
+               break;
        case MGSL_IOCTXENABLE:
-               return tx_enable(info, (int)arg);
+               ret = tx_enable(info, (int)arg);
+               break;
        case MGSL_IOCRXENABLE:
-               return rx_enable(info, (int)arg);
+               ret = rx_enable(info, (int)arg);
+               break;
        case MGSL_IOCTXABORT:
-               return tx_abort(info);
+               ret = tx_abort(info);
+               break;
        case MGSL_IOCGSTATS:
-               return get_stats(info, argp);
+               ret = get_stats(info, argp);
+               break;
        case MGSL_IOCWAITEVENT:
-               return wait_mgsl_event(info, argp);
+               ret = wait_mgsl_event(info, argp);
+               break;
        case TIOCMIWAIT:
-               return modem_input_wait(info,(int)arg);
+               ret = modem_input_wait(info,(int)arg);
+               break;
        case MGSL_IOCGIF:
-               return get_interface(info, argp);
+               ret = get_interface(info, argp);
+               break;
        case MGSL_IOCSIF:
-               return set_interface(info,(int)arg);
+               ret = set_interface(info,(int)arg);
+               break;
        case MGSL_IOCSGPIO:
-               return set_gpio(info, argp);
+               ret = set_gpio(info, argp);
+               break;
        case MGSL_IOCGGPIO:
-               return get_gpio(info, argp);
+               ret = get_gpio(info, argp);
+               break;
        case MGSL_IOCWAITGPIO:
-               return wait_gpio(info, argp);
+               ret = wait_gpio(info, argp);
+               break;
        case TIOCGICOUNT:
                spin_lock_irqsave(&info->lock,flags);
                cnow = info->icount;
@@ -1155,12 +1179,14 @@ static int ioctl(struct tty_struct *tty, struct file *file,
                    put_user(cnow.parity, &p_cuser->parity) ||
                    put_user(cnow.brk, &p_cuser->brk) ||
                    put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
-                       return -EFAULT;
-               return 0;
+                       ret = -EFAULT;
+               ret = 0;
+               break;
        default:
-               return -ENOIOCTLCMD;
+               ret = -ENOIOCTLCMD;
        }
-       return 0;
+       unlock_kernel();
+       return ret;
 }
 
 /*
@@ -3324,7 +3350,7 @@ static int claim_resources(struct slgt_info *info)
        else
                info->reg_addr_requested = true;
 
-       info->reg_addr = ioremap(info->phys_reg_addr, SLGT_REG_SIZE);
+       info->reg_addr = ioremap_nocache(info->phys_reg_addr, SLGT_REG_SIZE);
        if (!info->reg_addr) {
                DBGERR(("%s cant map device registers, addr=%08X\n",
                        info->device_name, info->phys_reg_addr));
index e98c3e6f8216dfca45215ca12d69f045565e12ca..bec54866e0bb6630b0f6d05f7890daf365695134 100644 (file)
@@ -519,7 +519,7 @@ static void hangup(struct tty_struct *tty);
 static void set_termios(struct tty_struct *tty, struct ktermios *old_termios);
 
 static int  write(struct tty_struct *tty, const unsigned char *buf, int count);
-static void put_char(struct tty_struct *tty, unsigned char ch);
+static int put_char(struct tty_struct *tty, unsigned char ch);
 static void send_xchar(struct tty_struct *tty, char ch);
 static void wait_until_sent(struct tty_struct *tty, int timeout);
 static int  write_room(struct tty_struct *tty);
@@ -862,8 +862,7 @@ static void close(struct tty_struct *tty, struct file *filp)
        if (info->flags & ASYNC_INITIALIZED)
                wait_until_sent(tty, info->timeout);
 
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       flush_buffer(tty);
 
        tty_ldisc_flush(tty);
 
@@ -1046,10 +1045,11 @@ cleanup:
 
 /* Add a character to the transmit buffer.
  */
-static void put_char(struct tty_struct *tty, unsigned char ch)
+static int put_char(struct tty_struct *tty, unsigned char ch)
 {
        SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
        unsigned long flags;
+       int ret = 0;
 
        if ( debug_level >= DEBUG_LEVEL_INFO ) {
                printk( "%s(%d):%s put_char(%d)\n",
@@ -1057,10 +1057,10 @@ static void put_char(struct tty_struct *tty, unsigned char ch)
        }
 
        if (sanity_check(info, tty->name, "put_char"))
-               return;
+               return 0;
 
        if (!info->tx_buf)
-               return;
+               return 0;
 
        spin_lock_irqsave(&info->lock,flags);
 
@@ -1072,10 +1072,12 @@ static void put_char(struct tty_struct *tty, unsigned char ch)
                        if (info->tx_put >= info->max_frame_size)
                                info->tx_put -= info->max_frame_size;
                        info->tx_count++;
+                       ret = 1;
                }
        }
 
        spin_unlock_irqrestore(&info->lock,flags);
+       return ret;
 }
 
 /* Send a high-priority XON/XOFF character
@@ -1119,6 +1121,8 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
        if (sanity_check(info, tty->name, "wait_until_sent"))
                return;
 
+       lock_kernel();
+
        if (!(info->flags & ASYNC_INITIALIZED))
                goto exit;
 
@@ -1161,6 +1165,7 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
        }
 
 exit:
+       unlock_kernel();
        if (debug_level >= DEBUG_LEVEL_INFO)
                printk("%s(%d):%s wait_until_sent() exit\n",
                         __FILE__,__LINE__, info->device_name );
@@ -1176,6 +1181,7 @@ static int write_room(struct tty_struct *tty)
        if (sanity_check(info, tty->name, "write_room"))
                return 0;
 
+       lock_kernel();
        if (info->params.mode == MGSL_MODE_HDLC) {
                ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE;
        } else {
@@ -1183,6 +1189,7 @@ static int write_room(struct tty_struct *tty)
                if (ret < 0)
                        ret = 0;
        }
+       unlock_kernel();
 
        if (debug_level >= DEBUG_LEVEL_INFO)
                printk("%s(%d):%s write_room()=%d\n",
@@ -1303,7 +1310,7 @@ static void tx_release(struct tty_struct *tty)
  *
  * Return Value:       0 if success, otherwise error code
  */
-static int ioctl(struct tty_struct *tty, struct file *file,
+static int do_ioctl(struct tty_struct *tty, struct file *file,
                 unsigned int cmd, unsigned long arg)
 {
        SLMP_INFO *info = (SLMP_INFO *)tty->driver_data;
@@ -1393,6 +1400,16 @@ static int ioctl(struct tty_struct *tty, struct file *file,
        return 0;
 }
 
+static int ioctl(struct tty_struct *tty, struct file *file,
+                unsigned int cmd, unsigned long arg)
+{
+       int ret;
+       lock_kernel();
+       ret = do_ioctl(tty, file, cmd, arg);
+       unlock_kernel();
+       return ret;
+}
+
 /*
  * /proc fs routines....
  */
@@ -3626,7 +3643,8 @@ static int claim_resources(SLMP_INFO *info)
        else
                info->sca_statctrl_requested = true;
 
-       info->memory_base = ioremap(info->phys_memory_base,SCA_MEM_SIZE);
+       info->memory_base = ioremap_nocache(info->phys_memory_base,
+                                                               SCA_MEM_SIZE);
        if (!info->memory_base) {
                printk( "%s(%d):%s Cant map shared memory, MemAddr=%08X\n",
                        __FILE__,__LINE__,info->device_name, info->phys_memory_base );
@@ -3634,7 +3652,7 @@ static int claim_resources(SLMP_INFO *info)
                goto errout;
        }
 
-       info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE);
+       info->lcr_base = ioremap_nocache(info->phys_lcr_base, PAGE_SIZE);
        if (!info->lcr_base) {
                printk( "%s(%d):%s Cant map LCR memory, MemAddr=%08X\n",
                        __FILE__,__LINE__,info->device_name, info->phys_lcr_base );
@@ -3643,7 +3661,7 @@ static int claim_resources(SLMP_INFO *info)
        }
        info->lcr_base += info->lcr_offset;
 
-       info->sca_base = ioremap(info->phys_sca_base,PAGE_SIZE);
+       info->sca_base = ioremap_nocache(info->phys_sca_base, PAGE_SIZE);
        if (!info->sca_base) {
                printk( "%s(%d):%s Cant map SCA memory, MemAddr=%08X\n",
                        __FILE__,__LINE__,info->device_name, info->phys_sca_base );
@@ -3652,7 +3670,8 @@ static int claim_resources(SLMP_INFO *info)
        }
        info->sca_base += info->sca_offset;
 
-       info->statctrl_base = ioremap(info->phys_statctrl_base,PAGE_SIZE);
+       info->statctrl_base = ioremap_nocache(info->phys_statctrl_base,
+                                                               PAGE_SIZE);
        if (!info->statctrl_base) {
                printk( "%s(%d):%s Cant map SCA Status/Control memory, MemAddr=%08X\n",
                        __FILE__,__LINE__,info->device_name, info->phys_statctrl_base );
index 1ade193c912816e6af11e0226c322e5653b13ec5..9e9bad8bdcf4e6725a982f92522b338bbf9731f3 100644 (file)
@@ -196,6 +196,48 @@ static struct sysrq_key_op sysrq_showlocks_op = {
 #define sysrq_showlocks_op (*(struct sysrq_key_op *)0)
 #endif
 
+#ifdef CONFIG_SMP
+static DEFINE_SPINLOCK(show_lock);
+
+static void showacpu(void *dummy)
+{
+       unsigned long flags;
+
+       /* Idle CPUs have no interesting backtrace. */
+       if (idle_cpu(smp_processor_id()))
+               return;
+
+       spin_lock_irqsave(&show_lock, flags);
+       printk(KERN_INFO "CPU%d:\n", smp_processor_id());
+       show_stack(NULL, NULL);
+       spin_unlock_irqrestore(&show_lock, flags);
+}
+
+static void sysrq_showregs_othercpus(struct work_struct *dummy)
+{
+       smp_call_function(showacpu, NULL, 0, 0);
+}
+
+static DECLARE_WORK(sysrq_showallcpus, sysrq_showregs_othercpus);
+
+static void sysrq_handle_showallcpus(int key, struct tty_struct *tty)
+{
+       struct pt_regs *regs = get_irq_regs();
+       if (regs) {
+               printk(KERN_INFO "CPU%d:\n", smp_processor_id());
+               show_regs(regs);
+       }
+       schedule_work(&sysrq_showallcpus);
+}
+
+static struct sysrq_key_op sysrq_showallcpus_op = {
+       .handler        = sysrq_handle_showallcpus,
+       .help_msg       = "aLlcpus",
+       .action_msg     = "Show backtrace of all active CPUs",
+       .enable_mask    = SYSRQ_ENABLE_DUMP,
+};
+#endif
+
 static void sysrq_handle_showregs(int key, struct tty_struct *tty)
 {
        struct pt_regs *regs = get_irq_regs();
@@ -340,7 +382,11 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
        &sysrq_kill_op,                 /* i */
        NULL,                           /* j */
        &sysrq_SAK_op,                  /* k */
+#ifdef CONFIG_SMP
+       &sysrq_showallcpus_op,          /* l */
+#else
        NULL,                           /* l */
+#endif
        &sysrq_showmem_op,              /* m */
        &sysrq_unrt_op,                 /* n */
        /* o: This will often be registered as 'Off' at init time */
index ce5ebe3b168ffe0cb59f83484370a2bf6d957602..64f1ceed0b2cbb3d4f72b8faad3a8459821f3ad0 100644 (file)
@@ -520,12 +520,11 @@ static int __init toshiba_init(void)
        {
                struct proc_dir_entry *pde;
 
-               pde = create_proc_entry("toshiba", 0, NULL);
+               pde = proc_create("toshiba", 0, NULL, &proc_toshiba_fops);
                if (!pde) {
                        misc_deregister(&tosh_device);
                        return -ENOMEM;
                }
-               pde->proc_fops = &proc_toshiba_fops;
        }
 #endif
 
index 8f3f7620f95a13afcc72b2fa36d142b1e5167303..3738cfa209ff2024b77d9790ea91777ab1783c83 100644 (file)
@@ -23,7 +23,7 @@ if TCG_TPM
 
 config TCG_TIS
        tristate "TPM Interface Specification 1.2 Interface"
-       depends on PNPACPI
+       depends on PNP
        ---help---
          If you have a TPM security chip that is compliant with the
          TCG TIS 1.2 TPM specification say Yes and it will be accessible
@@ -32,7 +32,6 @@ config TCG_TIS
 
 config TCG_NSC
        tristate "National Semiconductor TPM Interface"
-       depends on PNPACPI
        ---help---
          If you have a TPM security chip from National Semiconductor 
          say Yes and it will be accessible from within Linux.  To 
@@ -48,7 +47,7 @@ config TCG_ATMEL
 
 config TCG_INFINEON
        tristate "Infineon Technologies TPM Interface"
-       depends on PNPACPI
+       depends on PNP
        ---help---
          If you have a TPM security chip from Infineon Technologies
          (either SLD 9630 TT 1.1 or SLB 9635 TT 1.2) say Yes and it
index 6313326bc41fde5f2fdf455321af04abcede6181..ab18c1e7b115fd098ef56599241560d67fb19597 100644 (file)
@@ -264,7 +264,7 @@ static const struct tpm_vendor_specific tpm_nsc = {
 
 static struct platform_device *pdev = NULL;
 
-static void __devexit tpm_nsc_remove(struct device *dev)
+static void tpm_nsc_remove(struct device *dev)
 {
        struct tpm_chip *chip = dev_get_drvdata(dev);
        if ( chip ) {
index 7722466e052faedeb2ec999ba0b2f67f8b300e3e..6342b0534f4d3cda24aaac72cd5cb25deeb3021d 100644 (file)
@@ -92,7 +92,7 @@ static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
                get_task_comm(name, tsk);
                audit_log_untrustedstring(ab, name);
                audit_log_format(ab, " data=");
-               audit_log_n_untrustedstring(ab, buf->valid, buf->data);
+               audit_log_n_untrustedstring(ab, buf->data, buf->valid);
                audit_log_end(ab);
        }
        buf->valid = 0;
@@ -151,14 +151,9 @@ void tty_audit_fork(struct signal_struct *sig)
 /**
  *     tty_audit_push_task     -       Flush task's pending audit data
  */
-void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
+void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid, u32 sessionid)
 {
        struct tty_audit_buf *buf;
-       /* FIXME I think this is correct.  Check against netlink once that is
-        * I really need to read this code more closely.  But that's for
-        * another patch.
-        */
-       unsigned int sessionid = audit_get_sessionid(tsk);
 
        spin_lock_irq(&tsk->sighand->siglock);
        buf = tsk->signal->tty_audit_buf;
@@ -238,6 +233,10 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
        if (unlikely(size == 0))
                return;
 
+       if (tty->driver->type == TTY_DRIVER_TYPE_PTY
+           && tty->driver->subtype == PTY_TYPE_MASTER)
+               return;
+
        buf = tty_audit_buf_get(tty);
        if (!buf)
                return;
@@ -300,53 +299,3 @@ void tty_audit_push(struct tty_struct *tty)
                tty_audit_buf_put(buf);
        }
 }
-
-/**
- *     tty_audit_opening       -       A TTY is being opened.
- *
- *     As a special hack, tasks that close all their TTYs and open new ones
- *     are assumed to be system daemons (e.g. getty) and auditing is
- *     automatically disabled for them.
- */
-void tty_audit_opening(void)
-{
-       int disable;
-
-       disable = 1;
-       spin_lock_irq(&current->sighand->siglock);
-       if (current->signal->audit_tty == 0)
-               disable = 0;
-       spin_unlock_irq(&current->sighand->siglock);
-       if (!disable)
-               return;
-
-       task_lock(current);
-       if (current->files) {
-               struct fdtable *fdt;
-               unsigned i;
-
-               /*
-                * We don't take a ref to the file, so we must hold ->file_lock
-                * instead.
-                */
-               spin_lock(&current->files->file_lock);
-               fdt = files_fdtable(current->files);
-               for (i = 0; i < fdt->max_fds; i++) {
-                       struct file *filp;
-
-                       filp = fcheck_files(current->files, i);
-                       if (filp && is_tty(filp)) {
-                               disable = 0;
-                               break;
-                       }
-               }
-               spin_unlock(&current->files->file_lock);
-       }
-       task_unlock(current);
-       if (!disable)
-               return;
-
-       spin_lock_irq(&current->sighand->siglock);
-       current->signal->audit_tty = 0;
-       spin_unlock_irq(&current->sighand->siglock);
-}
index 98b65a2309943041f88690b6b50bddab096300be..1d298c2cf9301c0a1ac2026577463e6a3a6b1813 100644 (file)
@@ -91,7 +91,6 @@
 #include <linux/module.h>
 #include <linux/smp_lock.h>
 #include <linux/device.h>
-#include <linux/idr.h>
 #include <linux/wait.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
@@ -137,9 +136,6 @@ EXPORT_SYMBOL(tty_mutex);
 
 #ifdef CONFIG_UNIX98_PTYS
 extern struct tty_driver *ptm_driver;  /* Unix98 pty masters; for /dev/ptmx */
-extern int pty_limit;                  /* Config limit on Unix98 ptys */
-static DEFINE_IDR(allocated_ptys);
-static DEFINE_MUTEX(allocated_ptys_lock);
 static int ptmx_open(struct inode *, struct file *);
 #endif
 
@@ -152,8 +148,7 @@ ssize_t redirected_tty_write(struct file *, const char __user *,
 static unsigned int tty_poll(struct file *, poll_table *);
 static int tty_open(struct inode *, struct file *);
 static int tty_release(struct inode *, struct file *);
-int tty_ioctl(struct inode *inode, struct file *file,
-             unsigned int cmd, unsigned long arg);
+long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 #ifdef CONFIG_COMPAT
 static long tty_compat_ioctl(struct file *file, unsigned int cmd,
                                unsigned long arg);
@@ -1109,8 +1104,8 @@ restart:
           a reference to the old ldisc. If we ended up flipping back
           to the existing ldisc we have two references to it */
 
-       if (tty->ldisc.num != o_ldisc.num && tty->driver->set_ldisc)
-               tty->driver->set_ldisc(tty);
+       if (tty->ldisc.num != o_ldisc.num && tty->ops->set_ldisc)
+               tty->ops->set_ldisc(tty);
 
        tty_ldisc_put(o_ldisc.num);
 
@@ -1182,9 +1177,8 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line)
                if (*str == '\0')
                        str = NULL;
 
-               if (tty_line >= 0 && tty_line <= p->num && p->poll_init &&
-                               !p->poll_init(p, tty_line, str)) {
-
+               if (tty_line >= 0 && tty_line <= p->num && p->ops &&
+                   p->ops->poll_init && !p->ops->poll_init(p, tty_line, str)) {
                        res = p;
                        *line = tty_line;
                        break;
@@ -1205,26 +1199,37 @@ EXPORT_SYMBOL_GPL(tty_find_polling_driver);
  *     not in the foreground, send a SIGTTOU.  If the signal is blocked or
  *     ignored, go ahead and perform the operation.  (POSIX 7.2)
  *
- *     Locking: none
+ *     Locking: ctrl_lock
  */
 
 int tty_check_change(struct tty_struct *tty)
 {
+       unsigned long flags;
+       int ret = 0;
+
        if (current->signal->tty != tty)
                return 0;
+
+       spin_lock_irqsave(&tty->ctrl_lock, flags);
+
        if (!tty->pgrp) {
                printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n");
-               return 0;
+               goto out;
        }
        if (task_pgrp(current) == tty->pgrp)
-               return 0;
+               goto out;
        if (is_ignored(SIGTTOU))
-               return 0;
-       if (is_current_pgrp_orphaned())
-               return -EIO;
+               goto out;
+       if (is_current_pgrp_orphaned()) {
+               ret = -EIO;
+               goto out;
+       }
        kill_pgrp(task_pgrp(current), SIGTTOU, 1);
        set_thread_flag(TIF_SIGPENDING);
-       return -ERESTARTSYS;
+       ret = -ERESTARTSYS;
+out:
+       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+       return ret;
 }
 
 EXPORT_SYMBOL(tty_check_change);
@@ -1247,8 +1252,8 @@ static unsigned int hung_up_tty_poll(struct file *filp, poll_table *wait)
        return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM;
 }
 
-static int hung_up_tty_ioctl(struct inode *inode, struct file *file,
-                            unsigned int cmd, unsigned long arg)
+static long hung_up_tty_ioctl(struct file *file, unsigned int cmd,
+               unsigned long arg)
 {
        return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
 }
@@ -1264,7 +1269,7 @@ static const struct file_operations tty_fops = {
        .read           = tty_read,
        .write          = tty_write,
        .poll           = tty_poll,
-       .ioctl          = tty_ioctl,
+       .unlocked_ioctl = tty_ioctl,
        .compat_ioctl   = tty_compat_ioctl,
        .open           = tty_open,
        .release        = tty_release,
@@ -1277,7 +1282,7 @@ static const struct file_operations ptmx_fops = {
        .read           = tty_read,
        .write          = tty_write,
        .poll           = tty_poll,
-       .ioctl          = tty_ioctl,
+       .unlocked_ioctl = tty_ioctl,
        .compat_ioctl   = tty_compat_ioctl,
        .open           = ptmx_open,
        .release        = tty_release,
@@ -1290,7 +1295,7 @@ static const struct file_operations console_fops = {
        .read           = tty_read,
        .write          = redirected_tty_write,
        .poll           = tty_poll,
-       .ioctl          = tty_ioctl,
+       .unlocked_ioctl = tty_ioctl,
        .compat_ioctl   = tty_compat_ioctl,
        .open           = tty_open,
        .release        = tty_release,
@@ -1302,7 +1307,7 @@ static const struct file_operations hung_up_tty_fops = {
        .read           = hung_up_tty_read,
        .write          = hung_up_tty_write,
        .poll           = hung_up_tty_poll,
-       .ioctl          = hung_up_tty_ioctl,
+       .unlocked_ioctl = hung_up_tty_ioctl,
        .compat_ioctl   = hung_up_tty_compat_ioctl,
        .release        = tty_release,
 };
@@ -1404,6 +1409,7 @@ static void do_tty_hangup(struct work_struct *work)
        struct task_struct *p;
        struct tty_ldisc *ld;
        int    closecount = 0, n;
+       unsigned long flags;
 
        if (!tty)
                return;
@@ -1441,8 +1447,7 @@ static void do_tty_hangup(struct work_struct *work)
                /* We may have no line discipline at this point */
                if (ld->flush_buffer)
                        ld->flush_buffer(tty);
-               if (tty->driver->flush_buffer)
-                       tty->driver->flush_buffer(tty);
+               tty_driver_flush_buffer(tty);
                if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
                    ld->write_wakeup)
                        ld->write_wakeup(tty);
@@ -1480,19 +1485,24 @@ static void do_tty_hangup(struct work_struct *work)
                        __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
                        __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
                        put_pid(p->signal->tty_old_pgrp);  /* A noop */
+                       spin_lock_irqsave(&tty->ctrl_lock, flags);
                        if (tty->pgrp)
                                p->signal->tty_old_pgrp = get_pid(tty->pgrp);
+                       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
                        spin_unlock_irq(&p->sighand->siglock);
                } while_each_pid_task(tty->session, PIDTYPE_SID, p);
        }
        read_unlock(&tasklist_lock);
 
+       spin_lock_irqsave(&tty->ctrl_lock, flags);
        tty->flags = 0;
        put_pid(tty->session);
        put_pid(tty->pgrp);
        tty->session = NULL;
        tty->pgrp = NULL;
        tty->ctrl_status = 0;
+       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+
        /*
         * If one of the devices matches a console pointer, we
         * cannot just call hangup() because that will cause
@@ -1500,11 +1510,11 @@ static void do_tty_hangup(struct work_struct *work)
         * So we just call close() the right number of times.
         */
        if (cons_filp) {
-               if (tty->driver->close)
+               if (tty->ops->close)
                        for (n = 0; n < closecount; n++)
-                               tty->driver->close(tty, cons_filp);
-       } else if (tty->driver->hangup)
-               (tty->driver->hangup)(tty);
+                               tty->ops->close(tty, cons_filp);
+       } else if (tty->ops->hangup)
+               (tty->ops->hangup)(tty);
        /*
         * We don't want to have driver/ldisc interactions beyond
         * the ones we did here. The driver layer expects no
@@ -1626,16 +1636,17 @@ void disassociate_ctty(int on_exit)
        struct tty_struct *tty;
        struct pid *tty_pgrp = NULL;
 
-       lock_kernel();
 
        mutex_lock(&tty_mutex);
        tty = get_current_tty();
        if (tty) {
                tty_pgrp = get_pid(tty->pgrp);
                mutex_unlock(&tty_mutex);
+               lock_kernel();
                /* XXX: here we race, there is nothing protecting tty */
                if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
                        tty_vhangup(tty);
+               unlock_kernel();
        } else if (on_exit) {
                struct pid *old_pgrp;
                spin_lock_irq(&current->sighand->siglock);
@@ -1648,7 +1659,6 @@ void disassociate_ctty(int on_exit)
                        put_pid(old_pgrp);
                }
                mutex_unlock(&tty_mutex);
-               unlock_kernel();
                return;
        }
        if (tty_pgrp) {
@@ -1667,10 +1677,13 @@ void disassociate_ctty(int on_exit)
        /* It is possible that do_tty_hangup has free'd this tty */
        tty = get_current_tty();
        if (tty) {
+               unsigned long flags;
+               spin_lock_irqsave(&tty->ctrl_lock, flags);
                put_pid(tty->session);
                put_pid(tty->pgrp);
                tty->session = NULL;
                tty->pgrp = NULL;
+               spin_unlock_irqrestore(&tty->ctrl_lock, flags);
        } else {
 #ifdef TTY_DEBUG_HANGUP
                printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
@@ -1683,7 +1696,6 @@ void disassociate_ctty(int on_exit)
        read_lock(&tasklist_lock);
        session_clear_tty(task_session(current));
        read_unlock(&tasklist_lock);
-       unlock_kernel();
 }
 
 /**
@@ -1693,8 +1705,10 @@ void disassociate_ctty(int on_exit)
 void no_tty(void)
 {
        struct task_struct *tsk = current;
+       lock_kernel();
        if (tsk->signal->leader)
                disassociate_ctty(0);
+       unlock_kernel();
        proc_clear_tty(tsk);
 }
 
@@ -1714,21 +1728,26 @@ void no_tty(void)
  *     but not always.
  *
  *     Locking:
- *             Broken. Relies on BKL which is unsafe here.
+ *             Uses the tty control lock internally
  */
 
 void stop_tty(struct tty_struct *tty)
 {
-       if (tty->stopped)
+       unsigned long flags;
+       spin_lock_irqsave(&tty->ctrl_lock, flags);
+       if (tty->stopped) {
+               spin_unlock_irqrestore(&tty->ctrl_lock, flags);
                return;
+       }
        tty->stopped = 1;
        if (tty->link && tty->link->packet) {
                tty->ctrl_status &= ~TIOCPKT_START;
                tty->ctrl_status |= TIOCPKT_STOP;
                wake_up_interruptible(&tty->link->read_wait);
        }
-       if (tty->driver->stop)
-               (tty->driver->stop)(tty);
+       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+       if (tty->ops->stop)
+               (tty->ops->stop)(tty);
 }
 
 EXPORT_SYMBOL(stop_tty);
@@ -1743,21 +1762,26 @@ EXPORT_SYMBOL(stop_tty);
  *     driver start method is invoked and the line discipline woken.
  *
  *     Locking:
- *             Broken. Relies on BKL which is unsafe here.
+ *             ctrl_lock
  */
 
 void start_tty(struct tty_struct *tty)
 {
-       if (!tty->stopped || tty->flow_stopped)
+       unsigned long flags;
+       spin_lock_irqsave(&tty->ctrl_lock, flags);
+       if (!tty->stopped || tty->flow_stopped) {
+               spin_unlock_irqrestore(&tty->ctrl_lock, flags);
                return;
+       }
        tty->stopped = 0;
        if (tty->link && tty->link->packet) {
                tty->ctrl_status &= ~TIOCPKT_STOP;
                tty->ctrl_status |= TIOCPKT_START;
                wake_up_interruptible(&tty->link->read_wait);
        }
-       if (tty->driver->start)
-               (tty->driver->start)(tty);
+       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+       if (tty->ops->start)
+               (tty->ops->start)(tty);
        /* If we have a running line discipline it may need kicking */
        tty_wakeup(tty);
 }
@@ -1775,10 +1799,8 @@ EXPORT_SYMBOL(start_tty);
  *     for hung up devices before calling the line discipline method.
  *
  *     Locking:
- *             Locks the line discipline internally while needed
- *             For historical reasons the line discipline read method is
- *     invoked under the BKL. This will go away in time so do not rely on it
- *     in new code. Multiple read calls may be outstanding in parallel.
+ *             Locks the line discipline internally while needed. Multiple
+ *     read calls may be outstanding in parallel.
  */
 
 static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
@@ -1799,13 +1821,11 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
        /* We want to wait for the line discipline to sort out in this
           situation */
        ld = tty_ldisc_ref_wait(tty);
-       lock_kernel();
        if (ld->read)
                i = (ld->read)(tty, file, buf, count);
        else
                i = -EIO;
        tty_ldisc_deref(ld);
-       unlock_kernel();
        if (i > 0)
                inode->i_atime = current_fs_time(inode->i_sb);
        return i;
@@ -1893,9 +1913,7 @@ static inline ssize_t do_tty_write(
                ret = -EFAULT;
                if (copy_from_user(tty->write_buf, buf, size))
                        break;
-               lock_kernel();
                ret = write(tty, file, tty->write_buf, size);
-               unlock_kernel();
                if (ret <= 0)
                        break;
                written += ret;
@@ -1948,10 +1966,13 @@ static ssize_t tty_write(struct file *file, const char __user *buf,
        tty = (struct tty_struct *)file->private_data;
        if (tty_paranoia_check(tty, inode, "tty_write"))
                return -EIO;
-       if (!tty || !tty->driver->write ||
+       if (!tty || !tty->ops->write ||
                (test_bit(TTY_IO_ERROR, &tty->flags)))
                        return -EIO;
-
+       /* Short term debug to catch buggy drivers */
+       if (tty->ops->write_room == NULL)
+               printk(KERN_ERR "tty driver %s lacks a write_room method.\n",
+                       tty->driver->name);
        ld = tty_ldisc_ref_wait(tty);
        if (!ld->write)
                ret = -EIO;
@@ -2098,6 +2119,7 @@ static int init_dev(struct tty_driver *driver, int idx,
                goto fail_no_mem;
        initialize_tty_struct(tty);
        tty->driver = driver;
+       tty->ops = driver->ops;
        tty->index = idx;
        tty_line_name(driver, idx, tty->name);
 
@@ -2128,6 +2150,7 @@ static int init_dev(struct tty_driver *driver, int idx,
                        goto free_mem_out;
                initialize_tty_struct(o_tty);
                o_tty->driver = driver->other;
+               o_tty->ops = driver->ops;
                o_tty->index = idx;
                tty_line_name(driver->other, idx, o_tty->name);
 
@@ -2432,8 +2455,8 @@ static void release_dev(struct file *filp)
                }
        }
 #endif
-       if (tty->driver->close)
-               tty->driver->close(tty, filp);
+       if (tty->ops->close)
+               tty->ops->close(tty, filp);
 
        /*
         * Sanity check: if tty->count is going to zero, there shouldn't be
@@ -2612,15 +2635,9 @@ static void release_dev(struct file *filp)
         */
        release_tty(tty, idx);
 
-#ifdef CONFIG_UNIX98_PTYS
        /* Make this pty number available for reallocation */
-       if (devpts) {
-               mutex_lock(&allocated_ptys_lock);
-               idr_remove(&allocated_ptys, idx);
-               mutex_unlock(&allocated_ptys_lock);
-       }
-#endif
-
+       if (devpts)
+               devpts_kill_index(idx);
 }
 
 /**
@@ -2716,8 +2733,8 @@ got_driver:
        printk(KERN_DEBUG "opening %s...", tty->name);
 #endif
        if (!retval) {
-               if (tty->driver->open)
-                       retval = tty->driver->open(tty, filp);
+               if (tty->ops->open)
+                       retval = tty->ops->open(tty, filp);
                else
                        retval = -ENODEV;
        }
@@ -2755,7 +2772,6 @@ got_driver:
                __proc_set_tty(current, tty);
        spin_unlock_irq(&current->sighand->siglock);
        mutex_unlock(&tty_mutex);
-       tty_audit_opening();
        return 0;
 }
 
@@ -2777,29 +2793,13 @@ static int ptmx_open(struct inode *inode, struct file *filp)
        struct tty_struct *tty;
        int retval;
        int index;
-       int idr_ret;
 
        nonseekable_open(inode, filp);
 
        /* find a device that is not in use. */
-       mutex_lock(&allocated_ptys_lock);
-       if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) {
-               mutex_unlock(&allocated_ptys_lock);
-               return -ENOMEM;
-       }
-       idr_ret = idr_get_new(&allocated_ptys, NULL, &index);
-       if (idr_ret < 0) {
-               mutex_unlock(&allocated_ptys_lock);
-               if (idr_ret == -EAGAIN)
-                       return -ENOMEM;
-               return -EIO;
-       }
-       if (index >= pty_limit) {
-               idr_remove(&allocated_ptys, index);
-               mutex_unlock(&allocated_ptys_lock);
-               return -EIO;
-       }
-       mutex_unlock(&allocated_ptys_lock);
+       index = devpts_new_index();
+       if (index < 0)
+               return index;
 
        mutex_lock(&tty_mutex);
        retval = init_dev(ptm_driver, index, &tty);
@@ -2812,23 +2812,19 @@ static int ptmx_open(struct inode *inode, struct file *filp)
        filp->private_data = tty;
        file_move(filp, &tty->tty_files);
 
-       retval = -ENOMEM;
-       if (devpts_pty_new(tty->link))
+       retval = devpts_pty_new(tty->link);
+       if (retval)
                goto out1;
 
-       check_tty_count(tty, "tty_open");
-       retval = ptm_driver->open(tty, filp);
-       if (!retval) {
-               tty_audit_opening();
+       check_tty_count(tty, "ptmx_open");
+       retval = ptm_driver->ops->open(tty, filp);
+       if (!retval)
                return 0;
-       }
 out1:
        release_dev(filp);
        return retval;
 out:
-       mutex_lock(&allocated_ptys_lock);
-       idr_remove(&allocated_ptys, index);
-       mutex_unlock(&allocated_ptys_lock);
+       devpts_kill_index(index);
        return retval;
 }
 #endif
@@ -2885,6 +2881,7 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait)
 static int tty_fasync(int fd, struct file *filp, int on)
 {
        struct tty_struct *tty;
+       unsigned long flags;
        int retval;
 
        tty = (struct tty_struct *)filp->private_data;
@@ -2900,6 +2897,7 @@ static int tty_fasync(int fd, struct file *filp, int on)
                struct pid *pid;
                if (!waitqueue_active(&tty->read_wait))
                        tty->minimum_to_wake = 1;
+               spin_lock_irqsave(&tty->ctrl_lock, flags);
                if (tty->pgrp) {
                        pid = tty->pgrp;
                        type = PIDTYPE_PGID;
@@ -2907,6 +2905,7 @@ static int tty_fasync(int fd, struct file *filp, int on)
                        pid = task_pid(current);
                        type = PIDTYPE_PID;
                }
+               spin_unlock_irqrestore(&tty->ctrl_lock, flags);
                retval = __f_setown(filp, pid, type, 0);
                if (retval)
                        return retval;
@@ -2992,6 +2991,8 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
        struct winsize __user *arg)
 {
        struct winsize tmp_ws;
+       struct pid *pgrp, *rpgrp;
+       unsigned long flags;
 
        if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
                return -EFAULT;
@@ -3009,10 +3010,21 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
                }
        }
 #endif
-       if (tty->pgrp)
-               kill_pgrp(tty->pgrp, SIGWINCH, 1);
-       if ((real_tty->pgrp != tty->pgrp) && real_tty->pgrp)
-               kill_pgrp(real_tty->pgrp, SIGWINCH, 1);
+       /* Get the PID values and reference them so we can
+          avoid holding the tty ctrl lock while sending signals */
+       spin_lock_irqsave(&tty->ctrl_lock, flags);
+       pgrp = get_pid(tty->pgrp);
+       rpgrp = get_pid(real_tty->pgrp);
+       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+
+       if (pgrp)
+               kill_pgrp(pgrp, SIGWINCH, 1);
+       if (rpgrp != pgrp && rpgrp)
+               kill_pgrp(rpgrp, SIGWINCH, 1);
+
+       put_pid(pgrp);
+       put_pid(rpgrp);
+
        tty->winsize = tmp_ws;
        real_tty->winsize = tmp_ws;
 done:
@@ -3073,10 +3085,13 @@ static int fionbio(struct file *file, int __user *p)
        if (get_user(nonblock, p))
                return -EFAULT;
 
+       /* file->f_flags is still BKL protected in the fs layer - vomit */
+       lock_kernel();
        if (nonblock)
                file->f_flags |= O_NONBLOCK;
        else
                file->f_flags &= ~O_NONBLOCK;
+       unlock_kernel();
        return 0;
 }
 
@@ -3133,6 +3148,27 @@ unlock:
        return ret;
 }
 
+/**
+ *     tty_get_pgrp    -       return a ref counted pgrp pid
+ *     @tty: tty to read
+ *
+ *     Returns a refcounted instance of the pid struct for the process
+ *     group controlling the tty.
+ */
+
+struct pid *tty_get_pgrp(struct tty_struct *tty)
+{
+       unsigned long flags;
+       struct pid *pgrp;
+
+       spin_lock_irqsave(&tty->ctrl_lock, flags);
+       pgrp = get_pid(tty->pgrp);
+       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+
+       return pgrp;
+}
+EXPORT_SYMBOL_GPL(tty_get_pgrp);
+
 /**
  *     tiocgpgrp               -       get process group
  *     @tty: tty passed by user
@@ -3147,13 +3183,18 @@ unlock:
 
 static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
 {
+       struct pid *pid;
+       int ret;
        /*
         * (tty == real_tty) is a cheap way of
         * testing if the tty is NOT a master pty.
         */
        if (tty == real_tty && current->signal->tty != real_tty)
                return -ENOTTY;
-       return put_user(pid_vnr(real_tty->pgrp), p);
+       pid = tty_get_pgrp(real_tty);
+       ret =  put_user(pid_vnr(pid), p);
+       put_pid(pid);
+       return ret;
 }
 
 /**
@@ -3165,7 +3206,7 @@ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
  *     Set the process group of the tty to the session passed. Only
  *     permitted where the tty session is our session.
  *
- *     Locking: None
+ *     Locking: RCU, ctrl lock
  */
 
 static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
@@ -3173,6 +3214,7 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
        struct pid *pgrp;
        pid_t pgrp_nr;
        int retval = tty_check_change(real_tty);
+       unsigned long flags;
 
        if (retval == -EIO)
                return -ENOTTY;
@@ -3195,8 +3237,10 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
        if (session_of_pgrp(pgrp) != task_session(current))
                goto out_unlock;
        retval = 0;
+       spin_lock_irqsave(&tty->ctrl_lock, flags);
        put_pid(real_tty->pgrp);
        real_tty->pgrp = get_pid(pgrp);
+       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
 out_unlock:
        rcu_read_unlock();
        return retval;
@@ -3240,10 +3284,16 @@ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t _
 static int tiocsetd(struct tty_struct *tty, int __user *p)
 {
        int ldisc;
+       int ret;
 
        if (get_user(ldisc, p))
                return -EFAULT;
-       return tty_set_ldisc(tty, ldisc);
+
+       lock_kernel();
+       ret = tty_set_ldisc(tty, ldisc);
+       unlock_kernel();
+
+       return ret;
 }
 
 /**
@@ -3263,18 +3313,18 @@ static int send_break(struct tty_struct *tty, unsigned int duration)
 {
        if (tty_write_lock(tty, 0) < 0)
                return -EINTR;
-       tty->driver->break_ctl(tty, -1);
+       tty->ops->break_ctl(tty, -1);
        if (!signal_pending(current))
                msleep_interruptible(duration);
-       tty->driver->break_ctl(tty, 0);
+       tty->ops->break_ctl(tty, 0);
        tty_write_unlock(tty);
-       if (signal_pending(current))
+       if (!signal_pending(current))
                return -EINTR;
        return 0;
 }
 
 /**
- *     tiocmget                -       get modem status
+ *     tty_tiocmget            -       get modem status
  *     @tty: tty device
  *     @file: user file pointer
  *     @p: pointer to result
@@ -3289,8 +3339,8 @@ static int tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p
 {
        int retval = -EINVAL;
 
-       if (tty->driver->tiocmget) {
-               retval = tty->driver->tiocmget(tty, file);
+       if (tty->ops->tiocmget) {
+               retval = tty->ops->tiocmget(tty, file);
 
                if (retval >= 0)
                        retval = put_user(retval, p);
@@ -3299,7 +3349,7 @@ static int tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p
 }
 
 /**
- *     tiocmset                -       set modem status
+ *     tty_tiocmset            -       set modem status
  *     @tty: tty device
  *     @file: user file pointer
  *     @cmd: command - clear bits, set bits or set all
@@ -3316,7 +3366,7 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int
 {
        int retval = -EINVAL;
 
-       if (tty->driver->tiocmset) {
+       if (tty->ops->tiocmset) {
                unsigned int set, clear, val;
 
                retval = get_user(val, p);
@@ -3340,7 +3390,7 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int
                set &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
                clear &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
 
-               retval = tty->driver->tiocmset(tty, file, set, clear);
+               retval = tty->ops->tiocmset(tty, file, set, clear);
        }
        return retval;
 }
@@ -3348,20 +3398,18 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int
 /*
  * Split this up, as gcc can choke on it otherwise..
  */
-int tty_ioctl(struct inode *inode, struct file *file,
-             unsigned int cmd, unsigned long arg)
+long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        struct tty_struct *tty, *real_tty;
        void __user *p = (void __user *)arg;
        int retval;
        struct tty_ldisc *ld;
+       struct inode *inode = file->f_dentry->d_inode;
 
        tty = (struct tty_struct *)file->private_data;
        if (tty_paranoia_check(tty, inode, "tty_ioctl"))
                return -EINVAL;
 
-       /* CHECKME: is this safe as one end closes ? */
-
        real_tty = tty;
        if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
            tty->driver->subtype == PTY_TYPE_MASTER)
@@ -3370,21 +3418,28 @@ int tty_ioctl(struct inode *inode, struct file *file,
        /*
         * Break handling by driver
         */
-       if (!tty->driver->break_ctl) {
+
+       retval = -EINVAL;
+
+       if (!tty->ops->break_ctl) {
                switch (cmd) {
                case TIOCSBRK:
                case TIOCCBRK:
-                       if (tty->driver->ioctl)
-                               return tty->driver->ioctl(tty, file, cmd, arg);
-                       return -EINVAL;
+                       if (tty->ops->ioctl)
+                               retval = tty->ops->ioctl(tty, file, cmd, arg);
+                       if (retval != -EINVAL && retval != -ENOIOCTLCMD)
+                               printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name);
+                       return retval;
 
                /* These two ioctl's always return success; even if */
                /* the driver doesn't support them. */
                case TCSBRK:
                case TCSBRKP:
-                       if (!tty->driver->ioctl)
+                       if (!tty->ops->ioctl)
                                return 0;
-                       retval = tty->driver->ioctl(tty, file, cmd, arg);
+                       retval = tty->ops->ioctl(tty, file, cmd, arg);
+                       if (retval != -EINVAL && retval != -ENOIOCTLCMD)
+                               printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name);
                        if (retval == -ENOIOCTLCMD)
                                retval = 0;
                        return retval;
@@ -3442,7 +3497,6 @@ int tty_ioctl(struct inode *inode, struct file *file,
        case TIOCGSID:
                return tiocgsid(tty, real_tty, p);
        case TIOCGETD:
-               /* FIXME: check this is ok */
                return put_user(tty->ldisc.num, (int __user *)p);
        case TIOCSETD:
                return tiocsetd(tty, p);
@@ -3454,11 +3508,13 @@ int tty_ioctl(struct inode *inode, struct file *file,
         * Break handling
         */
        case TIOCSBRK:  /* Turn break on, unconditionally */
-               tty->driver->break_ctl(tty, -1);
+               if (tty->ops->break_ctl)
+                       tty->ops->break_ctl(tty, -1);
                return 0;
 
        case TIOCCBRK:  /* Turn break off, unconditionally */
-               tty->driver->break_ctl(tty, 0);
+               if (tty->ops->break_ctl)
+                       tty->ops->break_ctl(tty, 0);
                return 0;
        case TCSBRK:   /* SVID version: non-zero arg --> no break */
                /* non-zero arg means wait for all output data
@@ -3487,8 +3543,8 @@ int tty_ioctl(struct inode *inode, struct file *file,
                }
                break;
        }
-       if (tty->driver->ioctl) {
-               retval = (tty->driver->ioctl)(tty, file, cmd, arg);
+       if (tty->ops->ioctl) {
+               retval = (tty->ops->ioctl)(tty, file, cmd, arg);
                if (retval != -ENOIOCTLCMD)
                        return retval;
        }
@@ -3515,8 +3571,8 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd,
        if (tty_paranoia_check(tty, inode, "tty_ioctl"))
                return -EINVAL;
 
-       if (tty->driver->compat_ioctl) {
-               retval = (tty->driver->compat_ioctl)(tty, file, cmd, arg);
+       if (tty->ops->compat_ioctl) {
+               retval = (tty->ops->compat_ioctl)(tty, file, cmd, arg);
                if (retval != -ENOIOCTLCMD)
                        return retval;
        }
@@ -3566,8 +3622,7 @@ void __do_SAK(struct tty_struct *tty)
 
        tty_ldisc_flush(tty);
 
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       tty_driver_flush_buffer(tty);
 
        read_lock(&tasklist_lock);
        /* Kill the entire session */
@@ -3773,19 +3828,32 @@ static void initialize_tty_struct(struct tty_struct *tty)
        mutex_init(&tty->atomic_read_lock);
        mutex_init(&tty->atomic_write_lock);
        spin_lock_init(&tty->read_lock);
+       spin_lock_init(&tty->ctrl_lock);
        INIT_LIST_HEAD(&tty->tty_files);
        INIT_WORK(&tty->SAK_work, do_SAK_work);
 }
 
-/*
- * The default put_char routine if the driver did not define one.
+/**
+ *     tty_put_char    -       write one character to a tty
+ *     @tty: tty
+ *     @ch: character
+ *
+ *     Write one byte to the tty using the provided put_char method
+ *     if present. Returns the number of characters successfully output.
+ *
+ *     Note: the specific put_char operation in the driver layer may go
+ *     away soon. Don't call it directly, use this method
  */
 
-static void tty_default_put_char(struct tty_struct *tty, unsigned char ch)
+int tty_put_char(struct tty_struct *tty, unsigned char ch)
 {
-       tty->driver->write(tty, &ch, 1);
+       if (tty->ops->put_char)
+               return tty->ops->put_char(tty, ch);
+       return tty->ops->write(tty, &ch, 1);
 }
 
+EXPORT_SYMBOL_GPL(tty_put_char);
+
 static struct class *tty_class;
 
 /**
@@ -3868,37 +3936,8 @@ void put_tty_driver(struct tty_driver *driver)
 void tty_set_operations(struct tty_driver *driver,
                        const struct tty_operations *op)
 {
-       driver->open = op->open;
-       driver->close = op->close;
-       driver->write = op->write;
-       driver->put_char = op->put_char;
-       driver->flush_chars = op->flush_chars;
-       driver->write_room = op->write_room;
-       driver->chars_in_buffer = op->chars_in_buffer;
-       driver->ioctl = op->ioctl;
-       driver->compat_ioctl = op->compat_ioctl;
-       driver->set_termios = op->set_termios;
-       driver->throttle = op->throttle;
-       driver->unthrottle = op->unthrottle;
-       driver->stop = op->stop;
-       driver->start = op->start;
-       driver->hangup = op->hangup;
-       driver->break_ctl = op->break_ctl;
-       driver->flush_buffer = op->flush_buffer;
-       driver->set_ldisc = op->set_ldisc;
-       driver->wait_until_sent = op->wait_until_sent;
-       driver->send_xchar = op->send_xchar;
-       driver->read_proc = op->read_proc;
-       driver->write_proc = op->write_proc;
-       driver->tiocmget = op->tiocmget;
-       driver->tiocmset = op->tiocmset;
-#ifdef CONFIG_CONSOLE_POLL
-       driver->poll_init = op->poll_init;
-       driver->poll_get_char = op->poll_get_char;
-       driver->poll_put_char = op->poll_put_char;
-#endif
-}
-
+       driver->ops = op;
+};
 
 EXPORT_SYMBOL(alloc_tty_driver);
 EXPORT_SYMBOL(put_tty_driver);
@@ -3961,9 +4000,6 @@ int tty_register_driver(struct tty_driver *driver)
                return error;
        }
 
-       if (!driver->put_char)
-               driver->put_char = tty_default_put_char;
-
        mutex_lock(&tty_mutex);
        list_add(&driver->tty_drivers, &tty_drivers);
        mutex_unlock(&tty_mutex);
@@ -4039,14 +4075,19 @@ void proc_clear_tty(struct task_struct *p)
 }
 EXPORT_SYMBOL(proc_clear_tty);
 
+/* Called under the sighand lock */
+
 static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
 {
        if (tty) {
-               /* We should not have a session or pgrp to here but.... */
+               unsigned long flags;
+               /* We should not have a session or pgrp to put here but.... */
+               spin_lock_irqsave(&tty->ctrl_lock, flags);
                put_pid(tty->session);
                put_pid(tty->pgrp);
-               tty->session = get_pid(task_session(tsk));
                tty->pgrp = get_pid(task_pgrp(tsk));
+               spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+               tty->session = get_pid(task_session(tsk));
        }
        put_pid(tsk->signal->tty_old_pgrp);
        tsk->signal->tty = tty;
index f95a80b2265fdf0f42829f750c0c19f491eec044..b1a757a5ee271c9c4a4dc5a4b2fc18c35c7fb491 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/bitops.h>
 #include <linux/mutex.h>
+#include <linux/smp_lock.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #define TERMIOS_OLD    8
 
 
+int tty_chars_in_buffer(struct tty_struct *tty)
+{
+       if (tty->ops->chars_in_buffer)
+               return tty->ops->chars_in_buffer(tty);
+       else
+               return 0;
+}
+
+EXPORT_SYMBOL(tty_chars_in_buffer);
+
+int tty_write_room(struct tty_struct *tty)
+{
+       if (tty->ops->write_room)
+               return tty->ops->write_room(tty);
+       return 2048;
+}
+
+EXPORT_SYMBOL(tty_write_room);
+
+void tty_driver_flush_buffer(struct tty_struct *tty)
+{
+       if (tty->ops->flush_buffer)
+               tty->ops->flush_buffer(tty);
+}
+
+EXPORT_SYMBOL(tty_driver_flush_buffer);
+
+void tty_throttle(struct tty_struct *tty)
+{
+       /* check TTY_THROTTLED first so it indicates our state */
+       if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
+           tty->ops->throttle)
+               tty->ops->throttle(tty);
+}
+EXPORT_SYMBOL(tty_throttle);
+
+void tty_unthrottle(struct tty_struct *tty)
+{
+       if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
+           tty->ops->unthrottle)
+               tty->ops->unthrottle(tty);
+}
+EXPORT_SYMBOL(tty_unthrottle);
+
 /**
  *     tty_wait_until_sent     -       wait for I/O to finish
  *     @tty: tty we are waiting for
@@ -57,15 +102,13 @@ void tty_wait_until_sent(struct tty_struct *tty, long timeout)
 
        printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
 #endif
-       if (!tty->driver->chars_in_buffer)
-               return;
        if (!timeout)
                timeout = MAX_SCHEDULE_TIMEOUT;
        if (wait_event_interruptible_timeout(tty->write_wait,
-                       !tty->driver->chars_in_buffer(tty), timeout) < 0)
-               return;
-       if (tty->driver->wait_until_sent)
-               tty->driver->wait_until_sent(tty, timeout);
+                       !tty_chars_in_buffer(tty), timeout) >= 0) {
+               if (tty->ops->wait_until_sent)
+                       tty->ops->wait_until_sent(tty, timeout);
+       }
 }
 EXPORT_SYMBOL(tty_wait_until_sent);
 
@@ -393,8 +436,9 @@ EXPORT_SYMBOL(tty_termios_hw_change);
 static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
 {
        int canon_change;
-       struct ktermios old_termios = *tty->termios;
+       struct ktermios old_termios;
        struct tty_ldisc *ld;
+       unsigned long flags;
 
        /*
         *      Perform the actual termios internal changes under lock.
@@ -404,7 +448,7 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
        /* FIXME: we need to decide on some locking/ordering semantics
           for the set_termios notification eventually */
        mutex_lock(&tty->termios_mutex);
-
+       old_termios = *tty->termios;
        *tty->termios = *new_termios;
        unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
        canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
@@ -429,17 +473,19 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
                                STOP_CHAR(tty) == '\023' &&
                                START_CHAR(tty) == '\021');
                if (old_flow != new_flow) {
+                       spin_lock_irqsave(&tty->ctrl_lock, flags);
                        tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP);
                        if (new_flow)
                                tty->ctrl_status |= TIOCPKT_DOSTOP;
                        else
                                tty->ctrl_status |= TIOCPKT_NOSTOP;
+                       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
                        wake_up_interruptible(&tty->link->read_wait);
                }
        }
 
-       if (tty->driver->set_termios)
-               (*tty->driver->set_termios)(tty, &old_termios);
+       if (tty->ops->set_termios)
+               (*tty->ops->set_termios)(tty, &old_termios);
        else
                tty_termios_copy_hw(tty->termios, &old_termios);
 
@@ -474,7 +520,9 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
        if (retval)
                return retval;
 
+       mutex_lock(&tty->termios_mutex);
        memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
+       mutex_unlock(&tty->termios_mutex);
 
        if (opt & TERMIOS_TERMIO) {
                if (user_termio_to_kernel_termios(&tmp_termios,
@@ -660,12 +708,14 @@ static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
 {
        struct tchars tmp;
 
+       mutex_lock(&tty->termios_mutex);
        tmp.t_intrc = tty->termios->c_cc[VINTR];
        tmp.t_quitc = tty->termios->c_cc[VQUIT];
        tmp.t_startc = tty->termios->c_cc[VSTART];
        tmp.t_stopc = tty->termios->c_cc[VSTOP];
        tmp.t_eofc = tty->termios->c_cc[VEOF];
        tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
+       mutex_unlock(&tty->termios_mutex);
        return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 }
 
@@ -675,12 +725,14 @@ static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
 
        if (copy_from_user(&tmp, tchars, sizeof(tmp)))
                return -EFAULT;
+       mutex_lock(&tty->termios_mutex);
        tty->termios->c_cc[VINTR] = tmp.t_intrc;
        tty->termios->c_cc[VQUIT] = tmp.t_quitc;
        tty->termios->c_cc[VSTART] = tmp.t_startc;
        tty->termios->c_cc[VSTOP] = tmp.t_stopc;
        tty->termios->c_cc[VEOF] = tmp.t_eofc;
        tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
+       mutex_unlock(&tty->termios_mutex);
        return 0;
 }
 #endif
@@ -690,6 +742,7 @@ static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
 {
        struct ltchars tmp;
 
+       mutex_lock(&tty->termios_mutex);
        tmp.t_suspc = tty->termios->c_cc[VSUSP];
        /* what is dsuspc anyway? */
        tmp.t_dsuspc = tty->termios->c_cc[VSUSP];
@@ -698,6 +751,7 @@ static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
        tmp.t_flushc = tty->termios->c_cc[VEOL2];
        tmp.t_werasc = tty->termios->c_cc[VWERASE];
        tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
+       mutex_unlock(&tty->termios_mutex);
        return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 }
 
@@ -708,6 +762,7 @@ static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
        if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
                return -EFAULT;
 
+       mutex_lock(&tty->termios_mutex);
        tty->termios->c_cc[VSUSP] = tmp.t_suspc;
        /* what is dsuspc anyway? */
        tty->termios->c_cc[VEOL2] = tmp.t_dsuspc;
@@ -716,6 +771,7 @@ static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
        tty->termios->c_cc[VEOL2] = tmp.t_flushc;
        tty->termios->c_cc[VWERASE] = tmp.t_werasc;
        tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
+       mutex_unlock(&tty->termios_mutex);
        return 0;
 }
 #endif
@@ -732,8 +788,8 @@ static int send_prio_char(struct tty_struct *tty, char ch)
 {
        int     was_stopped = tty->stopped;
 
-       if (tty->driver->send_xchar) {
-               tty->driver->send_xchar(tty, ch);
+       if (tty->ops->send_xchar) {
+               tty->ops->send_xchar(tty, ch);
                return 0;
        }
 
@@ -742,13 +798,40 @@ static int send_prio_char(struct tty_struct *tty, char ch)
 
        if (was_stopped)
                start_tty(tty);
-       tty->driver->write(tty, &ch, 1);
+       tty->ops->write(tty, &ch, 1);
        if (was_stopped)
                stop_tty(tty);
        tty_write_unlock(tty);
        return 0;
 }
 
+/**
+ *     tty_change_softcar      -       carrier change ioctl helper
+ *     @tty: tty to update
+ *     @arg: enable/disable CLOCAL
+ *
+ *     Perform a change to the CLOCAL state and call into the driver
+ *     layer to make it visible. All done with the termios mutex
+ */
+
+static int tty_change_softcar(struct tty_struct *tty, int arg)
+{
+       int ret = 0;
+       int bit = arg ? CLOCAL : 0;
+       struct ktermios old;
+
+       mutex_lock(&tty->termios_mutex);
+       old = *tty->termios;
+       tty->termios->c_cflag &= ~CLOCAL;
+       tty->termios->c_cflag |= bit;
+       if (tty->ops->set_termios)
+               tty->ops->set_termios(tty, &old);
+       if ((tty->termios->c_cflag & CLOCAL) != bit)
+               ret = -EINVAL;
+       mutex_unlock(&tty->termios_mutex);
+       return ret;
+}
+
 /**
  *     tty_mode_ioctl          -       mode related ioctls
  *     @tty: tty for the ioctl
@@ -859,12 +942,7 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
        case TIOCSSOFTCAR:
                if (get_user(arg, (unsigned int __user *) arg))
                        return -EFAULT;
-               mutex_lock(&tty->termios_mutex);
-               tty->termios->c_cflag =
-                       ((tty->termios->c_cflag & ~CLOCAL) |
-                        (arg ? CLOCAL : 0));
-               mutex_unlock(&tty->termios_mutex);
-               return 0;
+               return tty_change_softcar(tty, arg);
        default:
                return -ENOIOCTLCMD;
        }
@@ -889,8 +967,7 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
                        ld->flush_buffer(tty);
                /* fall through */
        case TCOFLUSH:
-               if (tty->driver->flush_buffer)
-                       tty->driver->flush_buffer(tty);
+               tty_driver_flush_buffer(tty);
                break;
        default:
                tty_ldisc_deref(ld);
@@ -905,6 +982,7 @@ int n_tty_ioctl(struct tty_struct *tty, struct file *file,
                       unsigned int cmd, unsigned long arg)
 {
        struct tty_struct *real_tty;
+       unsigned long flags;
        int retval;
 
        if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
@@ -946,9 +1024,7 @@ int n_tty_ioctl(struct tty_struct *tty, struct file *file,
        case TCFLSH:
                return tty_perform_flush(tty, arg);
        case TIOCOUTQ:
-               return put_user(tty->driver->chars_in_buffer ?
-                               tty->driver->chars_in_buffer(tty) : 0,
-                               (int __user *) arg);
+               return put_user(tty_chars_in_buffer(tty), (int __user *) arg);
        case TIOCINQ:
                retval = tty->read_cnt;
                if (L_ICANON(tty))
@@ -963,6 +1039,7 @@ int n_tty_ioctl(struct tty_struct *tty, struct file *file,
                        return -ENOTTY;
                if (get_user(pktmode, (int __user *) arg))
                        return -EFAULT;
+               spin_lock_irqsave(&tty->ctrl_lock, flags);
                if (pktmode) {
                        if (!tty->packet) {
                                tty->packet = 1;
@@ -970,6 +1047,7 @@ int n_tty_ioctl(struct tty_struct *tty, struct file *file,
                        }
                } else
                        tty->packet = 0;
+               spin_unlock_irqrestore(&tty->ctrl_lock, flags);
                return 0;
        }
        default:
index 8de6b95aeb844cd03468d86f8643d2f65ed18acf..3d3e1c2b310f0abff4e60fdf6b6faf5fc7a322d0 100644 (file)
@@ -628,13 +628,13 @@ static int viotty_write(struct tty_struct *tty, const unsigned char *buf,
 /*
  * TTY put_char method
  */
-static void viotty_put_char(struct tty_struct *tty, unsigned char ch)
+static int viotty_put_char(struct tty_struct *tty, unsigned char ch)
 {
        struct port_info *pi;
 
        pi = get_port_data(tty);
        if (pi == NULL)
-               return;
+               return 0;
 
        /* This will append '\r' as well if the char is '\n' */
        if (viochar_is_console(pi))
@@ -642,6 +642,7 @@ static void viotty_put_char(struct tty_struct *tty, unsigned char ch)
 
        if (viopath_isactive(pi->lp))
                internal_write(pi, &ch, 1);
+       return 1;
 }
 
 /*
@@ -704,8 +705,11 @@ static int viotty_ioctl(struct tty_struct *tty, struct file *file,
        case KDSKBLED:
                return 0;
        }
-
-       return n_tty_ioctl(tty, file, cmd, arg);
+       /* FIXME: WTF is this being called for ??? */
+       lock_kernel();
+       ret =  n_tty_ioctl(tty, file, cmd, arg);
+       unlock_kernel();
+       return ret;
 }
 
 /*
index db7a731e2362dc747925991feb0fb06d3a86785c..58aad63831f4da854216bde2cd7b78ca87c0e7c0 100644 (file)
@@ -249,6 +249,7 @@ static int proc_viotape_open(struct inode *inode, struct file *file)
 }
 
 static const struct file_operations proc_viotape_operations = {
+       .owner          = THIS_MODULE,
        .open           = proc_viotape_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -915,7 +916,6 @@ static struct vio_driver viotape_driver = {
 int __init viotap_init(void)
 {
        int ret;
-       struct proc_dir_entry *e;
 
        if (!firmware_has_feature(FW_FEATURE_ISERIES))
                return -ENODEV;
@@ -968,11 +968,8 @@ int __init viotap_init(void)
        if (ret)
                goto unreg_class;
 
-       e = create_proc_entry("iSeries/viotape", S_IFREG|S_IRUGO, NULL);
-       if (e) {
-               e->owner = THIS_MODULE;
-               e->proc_fops = &proc_viotape_operations;
-       }
+       proc_create("iSeries/viotape", S_IFREG|S_IRUGO, NULL,
+                   &proc_viotape_operations);
 
        return 0;
 
index df4c3ead9e2b770664580a892b68249d7b04c786..e458b08139afb6fd638b125334ca1b602eb8e136 100644 (file)
@@ -301,7 +301,7 @@ static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
        d = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
        s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * (t + nr));
        scr_memmovew(d, s, (b - t - nr) * vc->vc_size_row);
-       scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_video_erase_char,
+       scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_scrl_erase_char,
                    vc->vc_size_row * nr);
 }
 
@@ -319,7 +319,7 @@ static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
        s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
        step = vc->vc_cols * nr;
        scr_memmovew(s + step, s, (b - t - nr) * vc->vc_size_row);
-       scr_memsetw(s, vc->vc_video_erase_char, 2 * step);
+       scr_memsetw(s, vc->vc_scrl_erase_char, 2 * step);
 }
 
 static void do_update_region(struct vc_data *vc, unsigned long start, int count)
@@ -400,7 +400,7 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink,
  *  Bit 7   : blink
  */
        {
-       u8 a = vc->vc_color;
+       u8 a = _color;
        if (!vc->vc_can_do_color)
                return _intensity |
                       (_italic ? 2 : 0) |
@@ -434,6 +434,7 @@ static void update_attr(struct vc_data *vc)
                      vc->vc_blink, vc->vc_underline,
                      vc->vc_reverse ^ vc->vc_decscnm, vc->vc_italic);
        vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm, 0) << 8) | ' ';
+       vc->vc_scrl_erase_char = (build_attr(vc, vc->vc_def_color, 1, false, false, false, false) << 8) | ' ';
 }
 
 /* Note: inverting the screen twice should revert to the original state */
@@ -908,15 +909,21 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
 
        if (vc->vc_tty) {
                struct winsize ws, *cws = &vc->vc_tty->winsize;
+               unsigned long flags;
 
                memset(&ws, 0, sizeof(ws));
                ws.ws_row = vc->vc_rows;
                ws.ws_col = vc->vc_cols;
                ws.ws_ypixel = vc->vc_scan_lines;
+
+               mutex_lock(&vc->vc_tty->termios_mutex);
+               spin_lock_irqsave(&vc->vc_tty->ctrl_lock, flags);
                if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) &&
                    vc->vc_tty->pgrp)
                        kill_pgrp(vc->vc_tty->pgrp, SIGWINCH, 1);
+               spin_unlock_irqrestore(&vc->vc_tty->ctrl_lock, flags);
                *cws = ws;
+               mutex_unlock(&vc->vc_tty->termios_mutex);
        }
 
        if (CON_IS_VISIBLE(vc))
@@ -2540,6 +2547,9 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
        if (get_user(type, p))
                return -EFAULT;
        ret = 0;
+
+       lock_kernel();
+
        switch (type)
        {
                case TIOCL_SETSEL:
@@ -2559,7 +2569,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
                        ret = sel_loadlut(p);
                        break;
                case TIOCL_GETSHIFTSTATE:
-                       
+
        /*
         * Make it possible to react to Shift+Mousebutton.
         * Note that 'shift_state' is an undocumented
@@ -2614,6 +2624,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
                        ret = -EINVAL;
                        break;
        }
+       unlock_kernel();
        return ret;
 }
 
@@ -2631,11 +2642,11 @@ static int con_write(struct tty_struct *tty, const unsigned char *buf, int count
        return retval;
 }
 
-static void con_put_char(struct tty_struct *tty, unsigned char ch)
+static int con_put_char(struct tty_struct *tty, unsigned char ch)
 {
        if (in_interrupt())
-               return; /* n_r3964 calls put_char() from interrupt context */
-       do_con_write(tty, &ch, 1);
+               return 0;       /* n_r3964 calls put_char() from interrupt context */
+       return do_con_write(tty, &ch, 1);
 }
 
 static int con_write_room(struct tty_struct *tty)
@@ -3828,7 +3839,7 @@ static int con_font_get(struct vc_data *vc, struct console_font_op *op)
                goto out;
 
        c = (font.width+7)/8 * 32 * font.charcount;
-       
+
        if (op->data && font.charcount > op->charcount)
                rc = -ENOSPC;
        if (!(op->flags & KD_FONT_FLAG_OLD)) {
@@ -3993,6 +4004,7 @@ u16 screen_glyph(struct vc_data *vc, int offset)
                c |= 0x100;
        return c;
 }
+EXPORT_SYMBOL_GPL(screen_glyph);
 
 /* used by vcs - note the word offset */
 unsigned short *screen_pos(struct vc_data *vc, int w_offset, int viewed)
index e6f89e8b9258429fc99754ec492918d94089bcfd..3211afd9d57e4080eb610c7bde54098a0c7bf117 100644 (file)
@@ -373,11 +373,17 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
        unsigned char ucval;
        void __user *up = (void __user *)arg;
        int i, perm;
-       
+       int ret = 0;
+
        console = vc->vc_num;
 
-       if (!vc_cons_allocated(console))        /* impossible? */
-               return -ENOIOCTLCMD;
+       lock_kernel();
+
+       if (!vc_cons_allocated(console)) {      /* impossible? */
+               ret = -ENOIOCTLCMD;
+               goto out;
+       }
+
 
        /*
         * To have permissions to do most of the vt ioctls, we either have
@@ -391,15 +397,15 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
        switch (cmd) {
        case KIOCSOUND:
                if (!perm)
-                       return -EPERM;
+                       goto eperm;
                if (arg)
                        arg = CLOCK_TICK_RATE / arg;
                kd_mksound(arg, 0);
-               return 0;
+               break;
 
        case KDMKTONE:
                if (!perm)
-                       return -EPERM;
+                       goto eperm;
        {
                unsigned int ticks, count;
                
@@ -412,7 +418,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                if (count)
                        count = CLOCK_TICK_RATE / count;
                kd_mksound(count, ticks);
-               return 0;
+               break;
        }
 
        case KDGKBTYPE:
@@ -435,14 +441,18 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                 * KDADDIO and KDDELIO may be able to add ports beyond what
                 * we reject here, but to be safe...
                 */
-               if (arg < GPFIRST || arg > GPLAST)
-                       return -EINVAL;
-               return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
+               if (arg < GPFIRST || arg > GPLAST) {
+                       ret = -EINVAL;
+                       break;
+               }
+               ret = sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
+               break;
 
        case KDENABIO:
        case KDDISABIO:
-               return sys_ioperm(GPFIRST, GPNUM,
+               ret = sys_ioperm(GPFIRST, GPNUM,
                                  (cmd == KDENABIO)) ? -ENXIO : 0;
+               break;
 #endif
 
        /* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */
@@ -450,19 +460,20 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
        case KDKBDREP:
        {
                struct kbd_repeat kbrep;
-               int err;
                
                if (!capable(CAP_SYS_TTY_CONFIG))
-                       return -EPERM;
+                       goto eperm;
 
-               if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat)))
-                       return -EFAULT;
-               err = kbd_rate(&kbrep);
-               if (err)
-                       return err;
+               if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat))) {
+                       ret =  -EFAULT;
+                       break;
+               }
+               ret = kbd_rate(&kbrep);
+               if (ret)
+                       break;
                if (copy_to_user(up, &kbrep, sizeof(struct kbd_repeat)))
-                       return -EFAULT;
-               return 0;
+                       ret = -EFAULT;
+               break;
        }
 
        case KDSETMODE:
@@ -475,7 +486,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                 * need to restore their engine state. --BenH
                 */
                if (!perm)
-                       return -EPERM;
+                       goto eperm;
                switch (arg) {
                case KD_GRAPHICS:
                        break;
@@ -485,13 +496,14 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                case KD_TEXT:
                        break;
                default:
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto out;
                }
                if (vc->vc_mode == (unsigned char) arg)
-                       return 0;
+                       break;
                vc->vc_mode = (unsigned char) arg;
                if (console != fg_console)
-                       return 0;
+                       break;
                /*
                 * explicitly blank/unblank the screen if switching modes
                 */
@@ -501,7 +513,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                else
                        do_blank_screen(1);
                release_console_sem();
-               return 0;
+               break;
 
        case KDGETMODE:
                ucval = vc->vc_mode;
@@ -513,11 +525,12 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                 * these work like a combination of mmap and KDENABIO.
                 * this could be easily finished.
                 */
-               return -EINVAL;
+               ret = -EINVAL;
+               break;
 
        case KDSKBMODE:
                if (!perm)
-                       return -EPERM;
+                       goto eperm;
                switch(arg) {
                  case K_RAW:
                        kbd->kbdmode = VC_RAW;
@@ -534,10 +547,11 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                        compute_shiftstate();
                        break;
                  default:
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto out;
                }
                tty_ldisc_flush(tty);
-               return 0;
+               break;
 
        case KDGKBMODE:
                ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
@@ -557,28 +571,32 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                        set_vc_kbd_mode(kbd, VC_META);
                        break;
                  default:
-                       return -EINVAL;
+                       ret = -EINVAL;
                }
-               return 0;
+               break;
 
        case KDGKBMETA:
                ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT);
        setint:
-               return put_user(ucval, (int __user *)arg); 
+               ret = put_user(ucval, (int __user *)arg);
+               break;
 
        case KDGETKEYCODE:
        case KDSETKEYCODE:
                if(!capable(CAP_SYS_TTY_CONFIG))
-                       perm=0;
-               return do_kbkeycode_ioctl(cmd, up, perm);
+                       perm = 0;
+               ret = do_kbkeycode_ioctl(cmd, up, perm);
+               break;
 
        case KDGKBENT:
        case KDSKBENT:
-               return do_kdsk_ioctl(cmd, up, perm, kbd);
+               ret = do_kdsk_ioctl(cmd, up, perm, kbd);
+               break;
 
        case KDGKBSENT:
        case KDSKBSENT:
-               return do_kdgkb_ioctl(cmd, up, perm);
+               ret = do_kdgkb_ioctl(cmd, up, perm);
+               break;
 
        case KDGKBDIACR:
        {
@@ -586,26 +604,31 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                struct kbdiacr diacr;
                int i;
 
-               if (put_user(accent_table_size, &a->kb_cnt))
-                       return -EFAULT;
+               if (put_user(accent_table_size, &a->kb_cnt)) {
+                       ret = -EFAULT;
+                       break;
+               }
                for (i = 0; i < accent_table_size; i++) {
                        diacr.diacr = conv_uni_to_8bit(accent_table[i].diacr);
                        diacr.base = conv_uni_to_8bit(accent_table[i].base);
                        diacr.result = conv_uni_to_8bit(accent_table[i].result);
-                       if (copy_to_user(a->kbdiacr + i, &diacr, sizeof(struct kbdiacr)))
-                               return -EFAULT;
+                       if (copy_to_user(a->kbdiacr + i, &diacr, sizeof(struct kbdiacr))) {
+                               ret = -EFAULT;
+                               break;
+                       }
                }
-               return 0;
+               break;
        }
        case KDGKBDIACRUC:
        {
                struct kbdiacrsuc __user *a = up;
 
                if (put_user(accent_table_size, &a->kb_cnt))
-                       return -EFAULT;
-               if (copy_to_user(a->kbdiacruc, accent_table, accent_table_size*sizeof(struct kbdiacruc)))
-                       return -EFAULT;
-               return 0;
+                       ret = -EFAULT;
+               else if (copy_to_user(a->kbdiacruc, accent_table,
+                               accent_table_size*sizeof(struct kbdiacruc)))
+                       ret = -EFAULT;
+               break;
        }
 
        case KDSKBDIACR:
@@ -616,20 +639,26 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                int i;
 
                if (!perm)
-                       return -EPERM;
-               if (get_user(ct,&a->kb_cnt))
-                       return -EFAULT;
-               if (ct >= MAX_DIACR)
-                       return -EINVAL;
+                       goto eperm;
+               if (get_user(ct,&a->kb_cnt)) {
+                       ret = -EFAULT;
+                       break;
+               }
+               if (ct >= MAX_DIACR) {
+                       ret = -EINVAL;
+                       break;
+               }
                accent_table_size = ct;
                for (i = 0; i < ct; i++) {
-                       if (copy_from_user(&diacr, a->kbdiacr + i, sizeof(struct kbdiacr)))
-                               return -EFAULT;
+                       if (copy_from_user(&diacr, a->kbdiacr + i, sizeof(struct kbdiacr))) {
+                               ret = -EFAULT;
+                               break;
+                       }
                        accent_table[i].diacr = conv_8bit_to_uni(diacr.diacr);
                        accent_table[i].base = conv_8bit_to_uni(diacr.base);
                        accent_table[i].result = conv_8bit_to_uni(diacr.result);
                }
-               return 0;
+               break;
        }
 
        case KDSKBDIACRUC:
@@ -638,15 +667,19 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                unsigned int ct;
 
                if (!perm)
-                       return -EPERM;
-               if (get_user(ct,&a->kb_cnt))
-                       return -EFAULT;
-               if (ct >= MAX_DIACR)
-                       return -EINVAL;
+                       goto eperm;
+               if (get_user(ct,&a->kb_cnt)) {
+                       ret = -EFAULT;
+                       break;
+               }
+               if (ct >= MAX_DIACR) {
+                       ret = -EINVAL;
+                       break;
+               }
                accent_table_size = ct;
                if (copy_from_user(accent_table, a->kbdiacruc, ct*sizeof(struct kbdiacruc)))
-                       return -EFAULT;
-               return 0;
+                       ret = -EFAULT;
+               break;
        }
 
        /* the ioctls below read/set the flags usually shown in the leds */
@@ -657,26 +690,29 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
 
        case KDSKBLED:
                if (!perm)
-                       return -EPERM;
-               if (arg & ~0x77)
-                       return -EINVAL;
+                       goto eperm;
+               if (arg & ~0x77) {
+                       ret = -EINVAL;
+                       break;
+               }
                kbd->ledflagstate = (arg & 7);
                kbd->default_ledflagstate = ((arg >> 4) & 7);
                set_leds();
-               return 0;
+               break;
 
        /* the ioctls below only set the lights, not the functions */
        /* for those, see KDGKBLED and KDSKBLED above */
        case KDGETLED:
                ucval = getledstate();
        setchar:
-               return put_user(ucval, (char __user *)arg);
+               ret = put_user(ucval, (char __user *)arg);
+               break;
 
        case KDSETLED:
                if (!perm)
-                 return -EPERM;
+                       goto eperm;
                setledstate(kbd, arg);
-               return 0;
+               break;
 
        /*
         * A process can indicate its willingness to accept signals
@@ -688,16 +724,17 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
        case KDSIGACCEPT:
        {
                if (!perm || !capable(CAP_KILL))
-                 return -EPERM;
+                       goto eperm;
                if (!valid_signal(arg) || arg < 1 || arg == SIGKILL)
-                 return -EINVAL;
-
-               spin_lock_irq(&vt_spawn_con.lock);
-               put_pid(vt_spawn_con.pid);
-               vt_spawn_con.pid = get_pid(task_pid(current));
-               vt_spawn_con.sig = arg;
-               spin_unlock_irq(&vt_spawn_con.lock);
-               return 0;
+                       ret = -EINVAL;
+               else {
+                       spin_lock_irq(&vt_spawn_con.lock);
+                       put_pid(vt_spawn_con.pid);
+                       vt_spawn_con.pid = get_pid(task_pid(current));
+                       vt_spawn_con.sig = arg;
+                       spin_unlock_irq(&vt_spawn_con.lock);
+               }
+               break;
        }
 
        case VT_SETMODE:
@@ -705,11 +742,15 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                struct vt_mode tmp;
 
                if (!perm)
-                       return -EPERM;
-               if (copy_from_user(&tmp, up, sizeof(struct vt_mode)))
-                       return -EFAULT;
-               if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS)
-                       return -EINVAL;
+                       goto eperm;
+               if (copy_from_user(&tmp, up, sizeof(struct vt_mode))) {
+                       ret = -EFAULT;
+                       goto out;
+               }
+               if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) {
+                       ret = -EINVAL;
+                       goto out;
+               }
                acquire_console_sem();
                vc->vt_mode = tmp;
                /* the frsig is ignored, so we set it to 0 */
@@ -719,7 +760,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                /* no switch is required -- saw@shade.msu.ru */
                vc->vt_newvt = -1;
                release_console_sem();
-               return 0;
+               break;
        }
 
        case VT_GETMODE:
@@ -732,7 +773,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                release_console_sem();
 
                rc = copy_to_user(up, &tmp, sizeof(struct vt_mode));
-               return rc ? -EFAULT : 0;
+               if (rc)
+                       ret = -EFAULT;
+               break;
        }
 
        /*
@@ -746,12 +789,16 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                unsigned short state, mask;
 
                if (put_user(fg_console + 1, &vtstat->v_active))
-                       return -EFAULT;
-               state = 1;      /* /dev/tty0 is always open */
-               for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
-                       if (VT_IS_IN_USE(i))
-                               state |= mask;
-               return put_user(state, &vtstat->v_state);
+                       ret = -EFAULT;
+               else {
+                       state = 1;      /* /dev/tty0 is always open */
+                       for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask;
+                                                       ++i, mask <<= 1)
+                               if (VT_IS_IN_USE(i))
+                                       state |= mask;
+                       ret = put_user(state, &vtstat->v_state);
+               }
+               break;
        }
 
        /*
@@ -771,27 +818,31 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
         */
        case VT_ACTIVATE:
                if (!perm)
-                       return -EPERM;
+                       goto eperm;
                if (arg == 0 || arg > MAX_NR_CONSOLES)
-                       return -ENXIO;
-               arg--;
-               acquire_console_sem();
-               i = vc_allocate(arg);
-               release_console_sem();
-               if (i)
-                       return i;
-               set_console(arg);
-               return 0;
+                       ret =  -ENXIO;
+               else {
+                       arg--;
+                       acquire_console_sem();
+                       ret = vc_allocate(arg);
+                       release_console_sem();
+                       if (ret)
+                               break;
+                       set_console(arg);
+               }
+               break;
 
        /*
         * wait until the specified VT has been activated
         */
        case VT_WAITACTIVE:
                if (!perm)
-                       return -EPERM;
+                       goto eperm;
                if (arg == 0 || arg > MAX_NR_CONSOLES)
-                       return -ENXIO;
-               return vt_waitactive(arg-1);
+                       ret = -ENXIO;
+               else
+                       ret = vt_waitactive(arg - 1);
+               break;
 
        /*
         * If a vt is under process control, the kernel will not switch to it
@@ -805,10 +856,12 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
         */
        case VT_RELDISP:
                if (!perm)
-                       return -EPERM;
-               if (vc->vt_mode.mode != VT_PROCESS)
-                       return -EINVAL;
+                       goto eperm;
 
+               if (vc->vt_mode.mode != VT_PROCESS) {
+                       ret = -EINVAL;
+                       break;
+               }
                /*
                 * Switching-from response
                 */
@@ -829,10 +882,10 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                                int newvt;
                                newvt = vc->vt_newvt;
                                vc->vt_newvt = -1;
-                               i = vc_allocate(newvt);
-                               if (i) {
+                               ret = vc_allocate(newvt);
+                               if (ret) {
                                        release_console_sem();
-                                       return i;
+                                       break;
                                }
                                /*
                                 * When we actually do the console switch,
@@ -841,31 +894,27 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                                 */
                                complete_change_console(vc_cons[newvt].d);
                        }
-               }
-
-               /*
-                * Switched-to response
-                */
-               else
-               {
+               } else {
+                       /*
+                        * Switched-to response
+                        */
                        /*
                         * If it's just an ACK, ignore it
                         */
-                       if (arg != VT_ACKACQ) {
-                               release_console_sem();
-                               return -EINVAL;
-                       }
+                       if (arg != VT_ACKACQ)
+                               ret = -EINVAL;
                }
                release_console_sem();
-
-               return 0;
+               break;
 
         /*
          * Disallocate memory associated to VT (but leave VT1)
          */
         case VT_DISALLOCATE:
-               if (arg > MAX_NR_CONSOLES)
-                       return -ENXIO;
+               if (arg > MAX_NR_CONSOLES) {
+                       ret = -ENXIO;
+                       break;
+               }
                if (arg == 0) {
                    /* deallocate all unused consoles, but leave 0 */
                        acquire_console_sem();
@@ -877,14 +926,14 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                        /* deallocate a single console, if possible */
                        arg--;
                        if (VT_BUSY(arg))
-                               return -EBUSY;
-                       if (arg) {                            /* leave 0 */
+                               ret = -EBUSY;
+                       else if (arg) {                       /* leave 0 */
                                acquire_console_sem();
                                vc_deallocate(arg);
                                release_console_sem();
                        }
                }
-               return 0;
+               break;
 
        case VT_RESIZE:
        {
@@ -893,21 +942,21 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
 
                ushort ll,cc;
                if (!perm)
-                       return -EPERM;
+                       goto eperm;
                if (get_user(ll, &vtsizes->v_rows) ||
                    get_user(cc, &vtsizes->v_cols))
-                       return -EFAULT;
-
-               for (i = 0; i < MAX_NR_CONSOLES; i++) {
-                       vc = vc_cons[i].d;
+                       ret = -EFAULT;
+               else {
+                       for (i = 0; i < MAX_NR_CONSOLES; i++) {
+                               vc = vc_cons[i].d;
 
-                       if (vc) {
-                               vc->vc_resize_user = 1;
-                               vc_lock_resize(vc_cons[i].d, cc, ll);
+                               if (vc) {
+                                       vc->vc_resize_user = 1;
+                                       vc_lock_resize(vc_cons[i].d, cc, ll);
+                               }
                        }
                }
-
-               return 0;
+               break;
        }
 
        case VT_RESIZEX:
@@ -915,10 +964,13 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                struct vt_consize __user *vtconsize = up;
                ushort ll,cc,vlin,clin,vcol,ccol;
                if (!perm)
-                       return -EPERM;
+                       goto eperm;
                if (!access_ok(VERIFY_READ, vtconsize,
-                               sizeof(struct vt_consize)))
-                       return -EFAULT;
+                               sizeof(struct vt_consize))) {
+                       ret = -EFAULT;
+                       break;
+               }
+               /* FIXME: Should check the copies properly */
                __get_user(ll, &vtconsize->v_rows);
                __get_user(cc, &vtconsize->v_cols);
                __get_user(vlin, &vtconsize->v_vlin);
@@ -928,21 +980,28 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                vlin = vlin ? vlin : vc->vc_scan_lines;
                if (clin) {
                        if (ll) {
-                               if (ll != vlin/clin)
-                                       return -EINVAL; /* Parameters don't add up */
+                               if (ll != vlin/clin) {
+                                       /* Parameters don't add up */
+                                       ret = -EINVAL;
+                                       break;
+                               }
                        } else 
                                ll = vlin/clin;
                }
                if (vcol && ccol) {
                        if (cc) {
-                               if (cc != vcol/ccol)
-                                       return -EINVAL;
+                               if (cc != vcol/ccol) {
+                                       ret = -EINVAL;
+                                       break;
+                               }
                        } else
                                cc = vcol/ccol;
                }
 
-               if (clin > 32)
-                       return -EINVAL;
+               if (clin > 32) {
+                       ret =  -EINVAL;
+                       break;
+               }
                    
                for (i = 0; i < MAX_NR_CONSOLES; i++) {
                        if (!vc_cons[i].d)
@@ -956,19 +1015,20 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                        vc_resize(vc_cons[i].d, cc, ll);
                        release_console_sem();
                }
-               return 0;
+               break;
        }
 
        case PIO_FONT: {
                if (!perm)
-                       return -EPERM;
+                       goto eperm;
                op.op = KD_FONT_OP_SET;
                op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */
                op.width = 8;
                op.height = 0;
                op.charcount = 256;
                op.data = up;
-               return con_font_op(vc_cons[fg_console].d, &op);
+               ret = con_font_op(vc_cons[fg_console].d, &op);
+               break;
        }
 
        case GIO_FONT: {
@@ -978,100 +1038,124 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                op.height = 32;
                op.charcount = 256;
                op.data = up;
-               return con_font_op(vc_cons[fg_console].d, &op);
+               ret = con_font_op(vc_cons[fg_console].d, &op);
+               break;
        }
 
        case PIO_CMAP:
                 if (!perm)
-                       return -EPERM;
-                return con_set_cmap(up);
+                       ret = -EPERM;
+               else
+                       ret = con_set_cmap(up);
+               break;
 
        case GIO_CMAP:
-                return con_get_cmap(up);
+                ret = con_get_cmap(up);
+               break;
 
        case PIO_FONTX:
        case GIO_FONTX:
-               return do_fontx_ioctl(cmd, up, perm, &op);
+               ret = do_fontx_ioctl(cmd, up, perm, &op);
+               break;
 
        case PIO_FONTRESET:
        {
                if (!perm)
-                       return -EPERM;
+                       goto eperm;
 
 #ifdef BROKEN_GRAPHICS_PROGRAMS
                /* With BROKEN_GRAPHICS_PROGRAMS defined, the default
                   font is not saved. */
-               return -ENOSYS;
+               ret = -ENOSYS;
+               break;
 #else
                {
                op.op = KD_FONT_OP_SET_DEFAULT;
                op.data = NULL;
-               i = con_font_op(vc_cons[fg_console].d, &op);
-               if (i)
-                       return i;
+               ret = con_font_op(vc_cons[fg_console].d, &op);
+               if (ret)
+                       break;
                con_set_default_unimap(vc_cons[fg_console].d);
-               return 0;
+               break;
                }
 #endif
        }
 
        case KDFONTOP: {
-               if (copy_from_user(&op, up, sizeof(op)))
-                       return -EFAULT;
+               if (copy_from_user(&op, up, sizeof(op))) {
+                       ret = -EFAULT;
+                       break;
+               }
                if (!perm && op.op != KD_FONT_OP_GET)
-                       return -EPERM;
-               i = con_font_op(vc, &op);
-               if (i) return i;
+                       goto eperm;
+               ret = con_font_op(vc, &op);
+               if (ret)
+                       break;
                if (copy_to_user(up, &op, sizeof(op)))
-                       return -EFAULT;
-               return 0;
+                       ret = -EFAULT;
+               break;
        }
 
        case PIO_SCRNMAP:
                if (!perm)
-                       return -EPERM;
-               return con_set_trans_old(up);
+                       ret = -EPERM;
+               else
+                       ret = con_set_trans_old(up);
+               break;
 
        case GIO_SCRNMAP:
-               return con_get_trans_old(up);
+               ret = con_get_trans_old(up);
+               break;
 
        case PIO_UNISCRNMAP:
                if (!perm)
-                       return -EPERM;
-               return con_set_trans_new(up);
+                       ret = -EPERM;
+               else
+                       ret = con_set_trans_new(up);
+               break;
 
        case GIO_UNISCRNMAP:
-               return con_get_trans_new(up);
+               ret = con_get_trans_new(up);
+               break;
 
        case PIO_UNIMAPCLR:
              { struct unimapinit ui;
                if (!perm)
-                       return -EPERM;
-               i = copy_from_user(&ui, up, sizeof(struct unimapinit));
-               if (i) return -EFAULT;
-               con_clear_unimap(vc, &ui);
-               return 0;
+                       goto eperm;
+               ret = copy_from_user(&ui, up, sizeof(struct unimapinit));
+               if (!ret)
+                       con_clear_unimap(vc, &ui);
+               break;
              }
 
        case PIO_UNIMAP:
        case GIO_UNIMAP:
-               return do_unimap_ioctl(cmd, up, perm, vc);
+               ret = do_unimap_ioctl(cmd, up, perm, vc);
+               break;
 
        case VT_LOCKSWITCH:
                if (!capable(CAP_SYS_TTY_CONFIG))
-                  return -EPERM;
+                       goto eperm;
                vt_dont_switch = 1;
-               return 0;
+               break;
        case VT_UNLOCKSWITCH:
                if (!capable(CAP_SYS_TTY_CONFIG))
-                  return -EPERM;
+                       goto eperm;
                vt_dont_switch = 0;
-               return 0;
+               break;
        case VT_GETHIFONTMASK:
-               return put_user(vc->vc_hi_font_mask, (unsigned short __user *)arg);
+               ret = put_user(vc->vc_hi_font_mask,
+                                       (unsigned short __user *)arg);
+               break;
        default:
-               return -ENOIOCTLCMD;
+               ret = -ENOIOCTLCMD;
        }
+out:
+       unlock_kernel();
+       return ret;
+eperm:
+       ret = -EPERM;
+       goto out;
 }
 
 /*
index c159ae64eeb2cf791d8aa36036e0480b8d3cf487..5f076aef74fa96d95959f84931d6ac42974d8b01 100644 (file)
@@ -69,6 +69,15 @@ config CPU_FREQ_DEFAULT_GOV_PERFORMANCE
          the frequency statically to the highest frequency supported by
          the CPU.
 
+config CPU_FREQ_DEFAULT_GOV_POWERSAVE
+       bool "powersave"
+       depends on EMBEDDED
+       select CPU_FREQ_GOV_POWERSAVE
+       help
+         Use the CPUFreq governor 'powersave' as default. This sets
+         the frequency statically to the lowest frequency supported by
+         the CPU.
+
 config CPU_FREQ_DEFAULT_GOV_USERSPACE
        bool "userspace"
        select CPU_FREQ_GOV_USERSPACE
index d3575f5ec6d23be5dbd1fe76d275e1c10b56a9e1..7fce038fa57e6413892679f6c8ca7256aeedafa3 100644 (file)
@@ -583,15 +583,13 @@ out:
        i += sprintf(&buf[i], "\n");
        return i;
 }
-/**
- * show_affected_cpus - show the CPUs affected by each transition
- */
-static ssize_t show_affected_cpus(struct cpufreq_policy *policy, char *buf)
+
+static ssize_t show_cpus(cpumask_t mask, char *buf)
 {
        ssize_t i = 0;
        unsigned int cpu;
 
-       for_each_cpu_mask(cpu, policy->cpus) {
+       for_each_cpu_mask(cpu, mask) {
                if (i)
                        i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), " ");
                i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), "%u", cpu);
@@ -602,6 +600,25 @@ static ssize_t show_affected_cpus(struct cpufreq_policy *policy, char *buf)
        return i;
 }
 
+/**
+ * show_related_cpus - show the CPUs affected by each transition even if
+ * hw coordination is in use
+ */
+static ssize_t show_related_cpus(struct cpufreq_policy *policy, char *buf)
+{
+       if (cpus_empty(policy->related_cpus))
+               return show_cpus(policy->cpus, buf);
+       return show_cpus(policy->related_cpus, buf);
+}
+
+/**
+ * show_affected_cpus - show the CPUs affected by each transition
+ */
+static ssize_t show_affected_cpus(struct cpufreq_policy *policy, char *buf)
+{
+       return show_cpus(policy->cpus, buf);
+}
+
 static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy,
                                        const char *buf, size_t count)
 {
@@ -646,6 +663,7 @@ define_one_ro(cpuinfo_max_freq);
 define_one_ro(scaling_available_governors);
 define_one_ro(scaling_driver);
 define_one_ro(scaling_cur_freq);
+define_one_ro(related_cpus);
 define_one_ro(affected_cpus);
 define_one_rw(scaling_min_freq);
 define_one_rw(scaling_max_freq);
@@ -658,6 +676,7 @@ static struct attribute *default_attrs[] = {
        &scaling_min_freq.attr,
        &scaling_max_freq.attr,
        &affected_cpus.attr,
+       &related_cpus.attr,
        &scaling_governor.attr,
        &scaling_driver.attr,
        &scaling_available_governors.attr,
index 13fe06b94b0a43c8e716c8e7625cecc5afc3b745..88d2f44fba480f7a66d00ed2fdeb571120926659 100644 (file)
@@ -35,12 +35,12 @@ static int cpufreq_governor_powersave(struct cpufreq_policy *policy,
        return 0;
 }
 
-static struct cpufreq_governor cpufreq_gov_powersave = {
+struct cpufreq_governor cpufreq_gov_powersave = {
        .name           = "powersave",
        .governor       = cpufreq_governor_powersave,
        .owner          = THIS_MODULE,
 };
-
+EXPORT_SYMBOL(cpufreq_gov_powersave);
 
 static int __init cpufreq_gov_powersave_init(void)
 {
@@ -58,5 +58,9 @@ MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
 MODULE_DESCRIPTION("CPUfreq policy governor 'powersave'");
 MODULE_LICENSE("GPL");
 
+#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE
+fs_initcall(cpufreq_gov_powersave_init);
+#else
 module_init(cpufreq_gov_powersave_init);
+#endif
 module_exit(cpufreq_gov_powersave_exit);
index ef09e069433b280c0dc58e0a51e6d0713a718a70..ae70d63a8b26eabb2b02d8c2ea28721fcd934b2a 100644 (file)
@@ -288,7 +288,7 @@ cpufreq_stat_notifier_trans (struct notifier_block *nb, unsigned long val,
        if (!stat)
                return 0;
 
-       old_index = freq_table_get_index(stat, freq->old);
+       old_index = stat->last_index;
        new_index = freq_table_get_index(stat, freq->new);
 
        cpufreq_stats_update(freq->cpu);
index 2b382990fe58772238eabd8e29b2485b95981778..6e6c3c4aea6b074d53c9824a1060bbfc38e88069 100644 (file)
@@ -67,7 +67,7 @@ config EDAC_E7XXX
          E7205, E7500, E7501 and E7505 server chipsets.
 
 config EDAC_E752X
-       tristate "Intel e752x (e7520, e7525, e7320)"
+       tristate "Intel e752x (e7520, e7525, e7320) and 3100"
        depends on EDAC_MM_EDAC && PCI && X86 && HOTPLUG
        help
          Support for error detection and correction on the Intel
index f22075410591a983fbb243fd42382448ac4d7640..2b95f1a3edfc318fe93ebf58b9bbd89cc8035599 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/slab.h>
+#include <linux/edac.h>
 #include "edac_core.h"
 
 #define AMD76X_REVISION        " Ver: 2.0.2 "  __DATE__
@@ -344,6 +345,9 @@ static struct pci_driver amd76x_driver = {
 
 static int __init amd76x_init(void)
 {
+       /* Ensure that the OPSTATE is set correctly for POLL or NMI */
+       opstate_init();
+
        return pci_register_driver(&amd76x_driver);
 }
 
@@ -358,3 +362,6 @@ module_exit(amd76x_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh");
 MODULE_DESCRIPTION("MC support for AMD 76x memory controllers");
+
+module_param(edac_op_state, int, 0444);
+MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
index 6eb434749cd5bad20ea376856c436b8f8587751b..c94a0eb492cb1eb2b01bfa5c8a5b47d7099c79a1 100644 (file)
@@ -29,6 +29,7 @@
 #define EDAC_MOD_STR   "e752x_edac"
 
 static int force_function_unhide;
+static int sysbus_parity = -1;
 
 static struct edac_pci_ctl_info *e752x_pci;
 
@@ -62,6 +63,14 @@ static struct edac_pci_ctl_info *e752x_pci;
 #define PCI_DEVICE_ID_INTEL_7320_1_ERR 0x3593
 #endif                         /* PCI_DEVICE_ID_INTEL_7320_1_ERR */
 
+#ifndef PCI_DEVICE_ID_INTEL_3100_0
+#define PCI_DEVICE_ID_INTEL_3100_0     0x35B0
+#endif                         /* PCI_DEVICE_ID_INTEL_3100_0 */
+
+#ifndef PCI_DEVICE_ID_INTEL_3100_1_ERR
+#define PCI_DEVICE_ID_INTEL_3100_1_ERR 0x35B1
+#endif                         /* PCI_DEVICE_ID_INTEL_3100_1_ERR */
+
 #define E752X_NR_CSROWS                8       /* number of csrows */
 
 /* E752X register addresses - device 0 function 0 */
@@ -152,6 +161,12 @@ static struct edac_pci_ctl_info *e752x_pci;
                                        /*     error syndrome register (16b) */
 #define E752X_DEVPRES1         0xF4    /* Device Present 1 register (8b) */
 
+/* 3100 IMCH specific register addresses - device 0 function 1 */
+#define I3100_NSI_FERR         0x48    /* NSI first error reg (32b) */
+#define I3100_NSI_NERR         0x4C    /* NSI next error reg (32b) */
+#define I3100_NSI_SMICMD       0x54    /* NSI SMI command register (32b) */
+#define I3100_NSI_EMASK                0x90    /* NSI error mask register (32b) */
+
 /* ICH5R register addresses - device 30 function 0 */
 #define ICH5R_PCI_STAT         0x06    /* PCI status register (16b) */
 #define ICH5R_PCI_2ND_STAT     0x1E    /* PCI status secondary reg (16b) */
@@ -160,7 +175,8 @@ static struct edac_pci_ctl_info *e752x_pci;
 enum e752x_chips {
        E7520 = 0,
        E7525 = 1,
-       E7320 = 2
+       E7320 = 2,
+       I3100 = 3
 };
 
 struct e752x_pvt {
@@ -185,8 +201,10 @@ struct e752x_dev_info {
 struct e752x_error_info {
        u32 ferr_global;
        u32 nerr_global;
-       u8 hi_ferr;
-       u8 hi_nerr;
+       u32 nsi_ferr;   /* 3100 only */
+       u32 nsi_nerr;   /* 3100 only */
+       u8 hi_ferr;     /* all but 3100 */
+       u8 hi_nerr;     /* all but 3100 */
        u16 sysbus_ferr;
        u16 sysbus_nerr;
        u8 buf_ferr;
@@ -215,6 +233,10 @@ static const struct e752x_dev_info e752x_devs[] = {
                .err_dev = PCI_DEVICE_ID_INTEL_7320_1_ERR,
                .ctl_dev = PCI_DEVICE_ID_INTEL_7320_0,
                .ctl_name = "E7320"},
+       [I3100] = {
+               .err_dev = PCI_DEVICE_ID_INTEL_3100_1_ERR,
+               .ctl_dev = PCI_DEVICE_ID_INTEL_3100_0,
+               .ctl_name = "3100"},
 };
 
 static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci,
@@ -402,7 +424,7 @@ static inline void process_threshold_ce(struct mem_ctl_info *mci, u16 error,
 static char *global_message[11] = {
        "PCI Express C1", "PCI Express C", "PCI Express B1",
        "PCI Express B", "PCI Express A1", "PCI Express A",
-       "DMA Controler", "HUB Interface", "System Bus",
+       "DMA Controler", "HUB or NS Interface", "System Bus",
        "DRAM Controler", "Internal Buffer"
 };
 
@@ -455,6 +477,63 @@ static inline void hub_error(int fatal, u8 errors, int *error_found,
                do_hub_error(fatal, errors);
 }
 
+#define NSI_FATAL_MASK         0x0c080081
+#define NSI_NON_FATAL_MASK     0x23a0ba64
+#define NSI_ERR_MASK           (NSI_FATAL_MASK | NSI_NON_FATAL_MASK)
+
+static char *nsi_message[30] = {
+       "NSI Link Down",        /* NSI_FERR/NSI_NERR bit 0, fatal error */
+       "",                                             /* reserved */
+       "NSI Parity Error",                             /* bit 2, non-fatal */
+       "",                                             /* reserved */
+       "",                                             /* reserved */
+       "Correctable Error Message",                    /* bit 5, non-fatal */
+       "Non-Fatal Error Message",                      /* bit 6, non-fatal */
+       "Fatal Error Message",                          /* bit 7, fatal */
+       "",                                             /* reserved */
+       "Receiver Error",                               /* bit 9, non-fatal */
+       "",                                             /* reserved */
+       "Bad TLP",                                      /* bit 11, non-fatal */
+       "Bad DLLP",                                     /* bit 12, non-fatal */
+       "REPLAY_NUM Rollover",                          /* bit 13, non-fatal */
+       "",                                             /* reserved */
+       "Replay Timer Timeout",                         /* bit 15, non-fatal */
+       "",                                             /* reserved */
+       "",                                             /* reserved */
+       "",                                             /* reserved */
+       "Data Link Protocol Error",                     /* bit 19, fatal */
+       "",                                             /* reserved */
+       "Poisoned TLP",                                 /* bit 21, non-fatal */
+       "",                                             /* reserved */
+       "Completion Timeout",                           /* bit 23, non-fatal */
+       "Completer Abort",                              /* bit 24, non-fatal */
+       "Unexpected Completion",                        /* bit 25, non-fatal */
+       "Receiver Overflow",                            /* bit 26, fatal */
+       "Malformed TLP",                                /* bit 27, fatal */
+       "",                                             /* reserved */
+       "Unsupported Request"                           /* bit 29, non-fatal */
+};
+
+static void do_nsi_error(int fatal, u32 errors)
+{
+       int i;
+
+       for (i = 0; i < 30; i++) {
+               if (errors & (1 << i))
+                       printk(KERN_WARNING "%sError %s\n",
+                              fatal_message[fatal], nsi_message[i]);
+       }
+}
+
+static inline void nsi_error(int fatal, u32 errors, int *error_found,
+               int handle_error)
+{
+       *error_found = 1;
+
+       if (handle_error)
+               do_nsi_error(fatal, errors);
+}
+
 static char *membuf_message[4] = {
        "Internal PMWB to DRAM parity",
        "Internal PMWB to System Bus Parity",
@@ -546,6 +625,31 @@ static void e752x_check_hub_interface(struct e752x_error_info *info,
        }
 }
 
+static void e752x_check_ns_interface(struct e752x_error_info *info,
+                               int *error_found, int handle_error)
+{
+       u32 stat32;
+
+       stat32 = info->nsi_ferr;
+       if (stat32 & NSI_ERR_MASK) { /* Error, so process */
+               if (stat32 & NSI_FATAL_MASK)    /* check for fatal errors */
+                       nsi_error(1, stat32 & NSI_FATAL_MASK, error_found,
+                                 handle_error);
+               if (stat32 & NSI_NON_FATAL_MASK) /* check for non-fatal ones */
+                       nsi_error(0, stat32 & NSI_NON_FATAL_MASK, error_found,
+                                 handle_error);
+       }
+       stat32 = info->nsi_nerr;
+       if (stat32 & NSI_ERR_MASK) {
+               if (stat32 & NSI_FATAL_MASK)
+                       nsi_error(1, stat32 & NSI_FATAL_MASK, error_found,
+                                 handle_error);
+               if (stat32 & NSI_NON_FATAL_MASK)
+                       nsi_error(0, stat32 & NSI_NON_FATAL_MASK, error_found,
+                                 handle_error);
+       }
+}
+
 static void e752x_check_sysbus(struct e752x_error_info *info,
                        int *error_found, int handle_error)
 {
@@ -653,7 +757,15 @@ static void e752x_get_error_info(struct mem_ctl_info *mci,
        pci_read_config_dword(dev, E752X_FERR_GLOBAL, &info->ferr_global);
 
        if (info->ferr_global) {
-               pci_read_config_byte(dev, E752X_HI_FERR, &info->hi_ferr);
+               if (pvt->dev_info->err_dev == PCI_DEVICE_ID_INTEL_3100_1_ERR) {
+                       pci_read_config_dword(dev, I3100_NSI_FERR,
+                                            &info->nsi_ferr);
+                       info->hi_ferr = 0;
+               } else {
+                       pci_read_config_byte(dev, E752X_HI_FERR,
+                                            &info->hi_ferr);
+                       info->nsi_ferr = 0;
+               }
                pci_read_config_word(dev, E752X_SYSBUS_FERR,
                                &info->sysbus_ferr);
                pci_read_config_byte(dev, E752X_BUF_FERR, &info->buf_ferr);
@@ -669,10 +781,15 @@ static void e752x_get_error_info(struct mem_ctl_info *mci,
                pci_read_config_dword(dev, E752X_DRAM_RETR_ADD,
                                &info->dram_retr_add);
 
+               /* ignore the reserved bits just in case */
                if (info->hi_ferr & 0x7f)
                        pci_write_config_byte(dev, E752X_HI_FERR,
                                        info->hi_ferr);
 
+               if (info->nsi_ferr & NSI_ERR_MASK)
+                       pci_write_config_dword(dev, I3100_NSI_FERR,
+                                       info->nsi_ferr);
+
                if (info->sysbus_ferr)
                        pci_write_config_word(dev, E752X_SYSBUS_FERR,
                                        info->sysbus_ferr);
@@ -692,7 +809,15 @@ static void e752x_get_error_info(struct mem_ctl_info *mci,
        pci_read_config_dword(dev, E752X_NERR_GLOBAL, &info->nerr_global);
 
        if (info->nerr_global) {
-               pci_read_config_byte(dev, E752X_HI_NERR, &info->hi_nerr);
+               if (pvt->dev_info->err_dev == PCI_DEVICE_ID_INTEL_3100_1_ERR) {
+                       pci_read_config_dword(dev, I3100_NSI_NERR,
+                                            &info->nsi_nerr);
+                       info->hi_nerr = 0;
+               } else {
+                       pci_read_config_byte(dev, E752X_HI_NERR,
+                                            &info->hi_nerr);
+                       info->nsi_nerr = 0;
+               }
                pci_read_config_word(dev, E752X_SYSBUS_NERR,
                                &info->sysbus_nerr);
                pci_read_config_byte(dev, E752X_BUF_NERR, &info->buf_nerr);
@@ -706,6 +831,10 @@ static void e752x_get_error_info(struct mem_ctl_info *mci,
                        pci_write_config_byte(dev, E752X_HI_NERR,
                                        info->hi_nerr);
 
+               if (info->nsi_nerr & NSI_ERR_MASK)
+                       pci_write_config_dword(dev, I3100_NSI_NERR,
+                                       info->nsi_nerr);
+
                if (info->sysbus_nerr)
                        pci_write_config_word(dev, E752X_SYSBUS_NERR,
                                        info->sysbus_nerr);
@@ -750,6 +879,7 @@ static int e752x_process_error_info(struct mem_ctl_info *mci,
                global_error(0, stat32, &error_found, handle_errors);
 
        e752x_check_hub_interface(info, &error_found, handle_errors);
+       e752x_check_ns_interface(info, &error_found, handle_errors);
        e752x_check_sysbus(info, &error_found, handle_errors);
        e752x_check_membuf(info, &error_found, handle_errors);
        e752x_check_dram(mci, info, &error_found, handle_errors);
@@ -920,15 +1050,53 @@ fail:
        return 1;
 }
 
+/* Setup system bus parity mask register.
+ * Sysbus parity supported on:
+ *   e7320/e7520/e7525 + Xeon
+ *   i3100 + Xeon/Celeron
+ * Sysbus parity not supported on:
+ *   i3100 + Pentium M/Celeron M/Core Duo/Core2 Duo
+ */
+static void e752x_init_sysbus_parity_mask(struct e752x_pvt *pvt)
+{
+       char *cpu_id = cpu_data(0).x86_model_id;
+       struct pci_dev *dev = pvt->dev_d0f1;
+       int enable = 1;
+
+       /* Allow module paramter override, else see if CPU supports parity */
+       if (sysbus_parity != -1) {
+               enable = sysbus_parity;
+       } else if (cpu_id[0] &&
+                  ((strstr(cpu_id, "Pentium") && strstr(cpu_id, " M ")) ||
+                   (strstr(cpu_id, "Celeron") && strstr(cpu_id, " M ")) ||
+                   (strstr(cpu_id, "Core") && strstr(cpu_id, "Duo")))) {
+               e752x_printk(KERN_INFO, "System Bus Parity not "
+                            "supported by CPU, disabling\n");
+               enable = 0;
+       }
+
+       if (enable)
+               pci_write_config_word(dev, E752X_SYSBUS_ERRMASK, 0x0000);
+       else
+               pci_write_config_word(dev, E752X_SYSBUS_ERRMASK, 0x0309);
+}
+
 static void e752x_init_error_reporting_regs(struct e752x_pvt *pvt)
 {
        struct pci_dev *dev;
 
        dev = pvt->dev_d0f1;
        /* Turn off error disable & SMI in case the BIOS turned it on */
-       pci_write_config_byte(dev, E752X_HI_ERRMASK, 0x00);
-       pci_write_config_byte(dev, E752X_HI_SMICMD, 0x00);
-       pci_write_config_word(dev, E752X_SYSBUS_ERRMASK, 0x00);
+       if (pvt->dev_info->err_dev == PCI_DEVICE_ID_INTEL_3100_1_ERR) {
+               pci_write_config_dword(dev, I3100_NSI_EMASK, 0);
+               pci_write_config_dword(dev, I3100_NSI_SMICMD, 0);
+       } else {
+               pci_write_config_byte(dev, E752X_HI_ERRMASK, 0x00);
+               pci_write_config_byte(dev, E752X_HI_SMICMD, 0x00);
+       }
+
+       e752x_init_sysbus_parity_mask(pvt);
+
        pci_write_config_word(dev, E752X_SYSBUS_SMICMD, 0x00);
        pci_write_config_byte(dev, E752X_BUF_ERRMASK, 0x00);
        pci_write_config_byte(dev, E752X_BUF_SMICMD, 0x00);
@@ -949,16 +1117,6 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
        debugf0("%s(): mci\n", __func__);
        debugf0("Starting Probe1\n");
 
-       /* make sure error reporting method is sane */
-       switch (edac_op_state) {
-       case EDAC_OPSTATE_POLL:
-       case EDAC_OPSTATE_NMI:
-               break;
-       default:
-               edac_op_state = EDAC_OPSTATE_POLL;
-               break;
-       }
-
        /* check to see if device 0 function 1 is enabled; if it isn't, we
         * assume the BIOS has reserved it for a reason and is expecting
         * exclusive access, we take care not to violate that assumption and
@@ -985,8 +1143,9 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
 
        debugf3("%s(): init mci\n", __func__);
        mci->mtype_cap = MEM_FLAG_RDDR;
-       mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED |
-               EDAC_FLAG_S4ECD4ED;
+       /* 3100 IMCH supports SECDEC only */
+       mci->edac_ctl_cap = (dev_idx == I3100) ? EDAC_FLAG_SECDED :
+               (EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED);
        /* FIXME - what if different memory types are in different csrows? */
        mci->mod_name = EDAC_MOD_STR;
        mci->mod_ver = E752X_REVISION;
@@ -1018,7 +1177,10 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
        e752x_init_csrows(mci, pdev, ddrcsr);
        e752x_init_mem_map_table(pdev, pvt);
 
-       mci->edac_cap |= EDAC_FLAG_NONE;
+       if (dev_idx == I3100)
+               mci->edac_cap = EDAC_FLAG_SECDED; /* the only mode supported */
+       else
+               mci->edac_cap |= EDAC_FLAG_NONE;
        debugf3("%s(): tolm, remapbase, remaplimit\n", __func__);
 
        /* load the top of low memory, remap base, and remap limit vars */
@@ -1109,6 +1271,9 @@ static const struct pci_device_id e752x_pci_tbl[] __devinitdata = {
        {
         PCI_VEND_DEV(INTEL, 7320_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
         E7320},
+       {
+        PCI_VEND_DEV(INTEL, 3100_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+        I3100},
        {
         0,
         }                      /* 0 terminated list. */
@@ -1128,6 +1293,10 @@ static int __init e752x_init(void)
        int pci_rc;
 
        debugf3("%s()\n", __func__);
+
+       /* Ensure that the OPSTATE is set correctly for POLL or NMI */
+       opstate_init();
+
        pci_rc = pci_register_driver(&e752x_driver);
        return (pci_rc < 0) ? pci_rc : 0;
 }
@@ -1143,10 +1312,15 @@ module_exit(e752x_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Linux Networx (http://lnxi.com) Tom Zimmerman\n");
-MODULE_DESCRIPTION("MC support for Intel e752x memory controllers");
+MODULE_DESCRIPTION("MC support for Intel e752x/3100 memory controllers");
 
 module_param(force_function_unhide, int, 0444);
 MODULE_PARM_DESC(force_function_unhide, "if BIOS sets Dev0:Fun1 up as hidden:"
                 " 1=force unhide and hope BIOS doesn't fight driver for Dev0:Fun1 access");
+
 module_param(edac_op_state, int, 0444);
 MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
+
+module_param(sysbus_parity, int, 0444);
+MODULE_PARM_DESC(sysbus_parity, "0=disable system bus parity checking,"
+               " 1=enable system bus parity checking, default=auto-detect");
index 96ecc492664122cb5025d9996353077642310957..c7d11cc4e21a5d608c96695f64cb29d78fb54f15 100644 (file)
@@ -414,16 +414,6 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
 
        debugf0("%s(): mci\n", __func__);
 
-       /* make sure error reporting method is sane */
-       switch (edac_op_state) {
-       case EDAC_OPSTATE_POLL:
-       case EDAC_OPSTATE_NMI:
-               break;
-       default:
-               edac_op_state = EDAC_OPSTATE_POLL;
-               break;
-       }
-
        pci_read_config_dword(pdev, E7XXX_DRC, &drc);
 
        drc_chan = dual_channel_active(drc, dev_idx);
@@ -565,6 +555,9 @@ static struct pci_driver e7xxx_driver = {
 
 static int __init e7xxx_init(void)
 {
+       /* Ensure that the OPSTATE is set correctly for POLL or NMI */
+       opstate_init();
+
        return pci_register_driver(&e7xxx_driver);
 }
 
index b9552bc03dead83ee02788de4c57979f038d54ad..63372fa7ecfe63ec6de319e4177a141c45bb508c 100644 (file)
@@ -36,7 +36,7 @@
  * is protected by the 'device_ctls_mutex' lock
  */
 static DEFINE_MUTEX(device_ctls_mutex);
-static struct list_head edac_device_list = LIST_HEAD_INIT(edac_device_list);
+static LIST_HEAD(edac_device_list);
 
 #ifdef CONFIG_EDAC_DEBUG
 static void edac_device_dump_device(struct edac_device_ctl_info *edac_dev)
@@ -375,37 +375,6 @@ static void del_edac_device_from_global_list(struct edac_device_ctl_info
        wait_for_completion(&edac_device->removal_complete);
 }
 
-/**
- * edac_device_find
- *     Search for a edac_device_ctl_info structure whose index is 'idx'.
- *
- * If found, return a pointer to the structure.
- * Else return NULL.
- *
- * Caller must hold device_ctls_mutex.
- */
-struct edac_device_ctl_info *edac_device_find(int idx)
-{
-       struct list_head *item;
-       struct edac_device_ctl_info *edac_dev;
-
-       /* Iterate over list, looking for exact match of ID */
-       list_for_each(item, &edac_device_list) {
-               edac_dev = list_entry(item, struct edac_device_ctl_info, link);
-
-               if (edac_dev->dev_idx >= idx) {
-                       if (edac_dev->dev_idx == idx)
-                               return edac_dev;
-
-                       /* not on list, so terminate early */
-                       break;
-               }
-       }
-
-       return NULL;
-}
-EXPORT_SYMBOL_GPL(edac_device_find);
-
 /*
  * edac_device_workq_function
  *     performs the operation scheduled by a workq request
index 063a1bffe38b026ba7005ee0b105a4e956baf6e9..a4cf1645f588c998bbebb4c812bd567a229cc0e2 100644 (file)
@@ -36,7 +36,7 @@
 
 /* lock to memory controller's control array */
 static DEFINE_MUTEX(mem_ctls_mutex);
-static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices);
+static LIST_HEAD(mc_devices);
 
 #ifdef CONFIG_EDAC_DEBUG
 
@@ -886,24 +886,3 @@ void edac_mc_handle_fbd_ce(struct mem_ctl_info *mci,
        mci->csrows[csrow].channels[channel].ce_count++;
 }
 EXPORT_SYMBOL(edac_mc_handle_fbd_ce);
-
-/*
- * Iterate over all MC instances and check for ECC, et al, errors
- */
-void edac_check_mc_devices(void)
-{
-       struct list_head *item;
-       struct mem_ctl_info *mci;
-
-       debugf3("%s()\n", __func__);
-       mutex_lock(&mem_ctls_mutex);
-
-       list_for_each(item, &mc_devices) {
-               mci = list_entry(item, struct mem_ctl_info, link);
-
-               if (mci->edac_check != NULL)
-                       mci->edac_check(mci);
-       }
-
-       mutex_unlock(&mem_ctls_mutex);
-}
index cbc419c8ebc1b8373c3c5661ce9a449cb3517107..233d4798c3aa2ecf18f3875d45a138b8bc2f2fe8 100644 (file)
@@ -27,7 +27,6 @@ extern int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci);
 extern void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci);
 extern int edac_create_sysfs_mci_device(struct mem_ctl_info *mci);
 extern void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci);
-extern void edac_check_mc_devices(void);
 extern int edac_get_log_ue(void);
 extern int edac_get_log_ce(void);
 extern int edac_get_panic_on_ue(void);
index 32be43576a8ee720876604a6b0c11c9081b2c0c7..9b24340b52e1eb3d30666181e668abf83ebd78f2 100644 (file)
@@ -29,7 +29,7 @@
 #include "edac_module.h"
 
 static DEFINE_MUTEX(edac_pci_ctls_mutex);
-static struct list_head edac_pci_list = LIST_HEAD_INIT(edac_pci_list);
+static LIST_HEAD(edac_pci_list);
 
 /*
  * edac_pci_alloc_ctl_info
@@ -189,6 +189,9 @@ static void del_edac_pci_from_global_list(struct edac_pci_ctl_info *pci)
        wait_for_completion(&pci->complete);
 }
 
+#if 0
+/* Older code, but might use in the future */
+
 /*
  * edac_pci_find()
  *     Search for an edac_pci_ctl_info structure whose index is 'idx'
@@ -219,6 +222,7 @@ struct edac_pci_ctl_info *edac_pci_find(int idx)
        return NULL;
 }
 EXPORT_SYMBOL_GPL(edac_pci_find);
+#endif
 
 /*
  * edac_pci_workq_function()
@@ -422,7 +426,7 @@ EXPORT_SYMBOL_GPL(edac_pci_del_device);
  *
  *     a Generic parity check API
  */
-void edac_pci_generic_check(struct edac_pci_ctl_info *pci)
+static void edac_pci_generic_check(struct edac_pci_ctl_info *pci)
 {
        debugf4("%s()\n", __func__);
        edac_pci_do_parity_check();
index 71c3195d3704428fc16a3f69848d739f0a8d723e..2c1fa1bb6df2fe87dbc96b3c511c24e509c43cf4 100644 (file)
@@ -37,17 +37,17 @@ int edac_pci_get_check_errors(void)
        return check_pci_errors;
 }
 
-int edac_pci_get_log_pe(void)
+static int edac_pci_get_log_pe(void)
 {
        return edac_pci_log_pe;
 }
 
-int edac_pci_get_log_npe(void)
+static int edac_pci_get_log_npe(void)
 {
        return edac_pci_log_npe;
 }
 
-int edac_pci_get_panic_on_pe(void)
+static int edac_pci_get_panic_on_pe(void)
 {
        return edac_pci_panic_on_pe;
 }
@@ -197,7 +197,8 @@ error_out:
  *
  *     unregister the kobj for the EDAC PCI instance
  */
-void edac_pci_unregister_sysfs_instance_kobj(struct edac_pci_ctl_info *pci)
+static void edac_pci_unregister_sysfs_instance_kobj(
+                       struct edac_pci_ctl_info *pci)
 {
        debugf0("%s()\n", __func__);
 
@@ -337,7 +338,7 @@ static struct kobj_type ktype_edac_pci_main_kobj = {
  *     setup the sysfs for EDAC PCI attributes
  *     assumes edac_class has already been initialized
  */
-int edac_pci_main_kobj_setup(void)
+static int edac_pci_main_kobj_setup(void)
 {
        int err;
        struct sysdev_class *edac_class;
index 5d4292811c146285f45acc0f47ebe0618d210127..6c9a0f2a593cd89fbc998182798bf1e21894d5ea 100644 (file)
@@ -326,15 +326,6 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx)
                return -ENODEV;
        }
 
-       switch (edac_op_state) {
-       case EDAC_OPSTATE_POLL:
-       case EDAC_OPSTATE_NMI:
-               break;
-       default:
-               edac_op_state = EDAC_OPSTATE_POLL;
-               break;
-       }
-
        c0dra[0] = readb(window + I3000_C0DRA + 0);     /* ranks 0,1 */
        c0dra[1] = readb(window + I3000_C0DRA + 1);     /* ranks 2,3 */
        c1dra[0] = readb(window + I3000_C1DRA + 0);     /* ranks 0,1 */
@@ -503,6 +494,10 @@ static int __init i3000_init(void)
        int pci_rc;
 
        debugf3("MC: %s()\n", __func__);
+
+       /* Ensure that the OPSTATE is set correctly for POLL or NMI */
+       opstate_init();
+
        pci_rc = pci_register_driver(&i3000_driver);
        if (pci_rc < 0)
                goto fail0;
index 5a852017c17a70dc87d1bd16c7e83587b8b7a1c7..4a16b5b61cfbdc702530e735af2bbb7a0eac1d2b 100644 (file)
@@ -1286,16 +1286,6 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx)
        if (PCI_FUNC(pdev->devfn) != 0)
                return -ENODEV;
 
-       /* make sure error reporting method is sane */
-       switch (edac_op_state) {
-       case EDAC_OPSTATE_POLL:
-       case EDAC_OPSTATE_NMI:
-               break;
-       default:
-               edac_op_state = EDAC_OPSTATE_POLL;
-               break;
-       }
-
        /* Ask the devices for the number of CSROWS and CHANNELS so
         * that we can calculate the memory resources, etc
         *
@@ -1478,6 +1468,9 @@ static int __init i5000_init(void)
 
        debugf2("MC: " __FILE__ ": %s()\n", __func__);
 
+       /* Ensure that the OPSTATE is set correctly for POLL or NMI */
+       opstate_init();
+
        pci_rc = pci_register_driver(&i5000_driver);
 
        return (pci_rc < 0) ? pci_rc : 0;
@@ -1501,5 +1494,6 @@ MODULE_AUTHOR
     ("Linux Networx (http://lnxi.com) Doug Thompson <norsk5@xmission.com>");
 MODULE_DESCRIPTION("MC Driver for Intel I5000 memory controllers - "
                I5000_REVISION);
+
 module_param(edac_op_state, int, 0444);
 MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
index 83bfe37c4bbbbabe3ec051e34aa7a6149257b203..c5305e3ee4346932b44cc73074cb6718bd3a38ad 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <linux/slab.h>
 
+#include <linux/edac.h>
 #include "edac_core.h"
 
 #define I82443_REVISION        "0.1"
@@ -386,6 +387,9 @@ static struct pci_driver i82443bxgx_edacmc_driver = {
 
 static int __init i82443bxgx_edacmc_init(void)
 {
+       /* Ensure that the OPSTATE is set correctly for POLL or NMI */
+       opstate_init();
+
        return pci_register_driver(&i82443bxgx_edacmc_driver);
 }
 
@@ -400,3 +404,6 @@ module_exit(i82443bxgx_edacmc_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Tim Small <tim@buttersideup.com> - WPAD");
 MODULE_DESCRIPTION("EDAC MC support for Intel 82443BX/GX memory controllers");
+
+module_param(edac_op_state, int, 0444);
+MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
index f5ecd2c4d813eb9439bcffb6a69addbfd7e724ff..c0088ba9672b754429d0bcd8bea19329f36c4064 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/slab.h>
+#include <linux/edac.h>
 #include "edac_core.h"
 
 #define  I82860_REVISION " Ver: 2.0.2 " __DATE__
@@ -294,6 +295,9 @@ static int __init i82860_init(void)
 
        debugf3("%s()\n", __func__);
 
+       /* Ensure that the OPSTATE is set correctly for POLL or NMI */
+       opstate_init();
+
        if ((pci_rc = pci_register_driver(&i82860_driver)) < 0)
                goto fail0;
 
@@ -345,3 +349,6 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com) "
                "Ben Woodard <woodard@redhat.com>");
 MODULE_DESCRIPTION("ECC support for Intel 82860 memory hub controllers");
+
+module_param(edac_op_state, int, 0444);
+MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
index 031abadc439a37c407d213fd1091b8e9a03b745e..e43bdc43a1bf09732a7f9037b76852968c24c4f5 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/slab.h>
+#include <linux/edac.h>
 #include "edac_core.h"
 
 #define I82875P_REVISION       " Ver: 2.0.2 " __DATE__
@@ -393,6 +394,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
        struct i82875p_error_info discard;
 
        debugf0("%s()\n", __func__);
+
        ovrfl_pdev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL);
 
        if (i82875p_setup_overfl_dev(pdev, &ovrfl_pdev, &ovrfl_window))
@@ -532,6 +534,10 @@ static int __init i82875p_init(void)
        int pci_rc;
 
        debugf3("%s()\n", __func__);
+
+       /* Ensure that the OPSTATE is set correctly for POLL or NMI */
+       opstate_init();
+
        pci_rc = pci_register_driver(&i82875p_driver);
 
        if (pci_rc < 0)
@@ -586,3 +592,6 @@ module_exit(i82875p_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh");
 MODULE_DESCRIPTION("MC support for Intel 82875 memory hub controllers");
+
+module_param(edac_op_state, int, 0444);
+MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
index 0ee888456932e4f0f95e59ab135b02e80d6f23ca..2eed3ea2cf621303320aec118f0ed3bcfcd9764f 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/slab.h>
-
+#include <linux/edac.h>
 #include "edac_core.h"
 
 #define I82975X_REVISION       " Ver: 1.0.0 " __DATE__
@@ -611,6 +611,9 @@ static int __init i82975x_init(void)
 
        debugf3("%s()\n", __func__);
 
+       /* Ensure that the OPSTATE is set correctly for POLL or NMI */
+       opstate_init();
+
        pci_rc = pci_register_driver(&i82975x_driver);
        if (pci_rc < 0)
                goto fail0;
@@ -664,3 +667,6 @@ module_exit(i82975x_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Arvind R. <arvind@acarlab.com>");
 MODULE_DESCRIPTION("MC support for Intel 82975 memory hub controllers");
+
+module_param(edac_op_state, int, 0444);
+MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
index 90320917be2875a6a0fc77361fd59e254f7670f6..8e6b91bd2e99994525cba93fbdaac6750ec6da23 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/slab.h>
+#include <linux/edac.h>
 #include "edac_core.h"
 
 #define MODULE_NAME "pasemi_edac"
@@ -284,6 +285,9 @@ static struct pci_driver pasemi_edac_driver = {
 
 static int __init pasemi_edac_init(void)
 {
+       /* Ensure that the OPSTATE is set correctly for POLL or NMI */
+       opstate_init();
+
        return pci_register_driver(&pasemi_edac_driver);
 }
 
@@ -298,3 +302,6 @@ module_exit(pasemi_edac_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>");
 MODULE_DESCRIPTION("MC support for PA Semi PWRficient memory controller");
+module_param(edac_op_state, int, 0444);
+MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
+
index e25f712f2dc3b8479e224d6bae80d9765304166b..9900675e9598c25006dd696f6f4d20af3694a223 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/slab.h>
+#include <linux/edac.h>
 #include "edac_core.h"
 
 #define R82600_REVISION        " Ver: 2.0.2 " __DATE__
@@ -393,6 +394,9 @@ static struct pci_driver r82600_driver = {
 
 static int __init r82600_init(void)
 {
+       /* Ensure that the OPSTATE is set correctly for POLL or NMI */
+       opstate_init();
+
        return pci_register_driver(&r82600_driver);
 }
 
@@ -412,3 +416,6 @@ MODULE_DESCRIPTION("MC support for Radisys 82600 memory controllers");
 module_param(disable_hardware_scrub, bool, 0644);
 MODULE_PARM_DESC(disable_hardware_scrub,
                 "If set, disable the chipset's automatic scrub for CEs");
+
+module_param(edac_op_state, int, 0444);
+MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
index 40ffd767647d623baa1259618b8912ef8ecc863d..dc2cec6127d1816982558de72a2ee9e4c1b884a5 100644 (file)
@@ -17,6 +17,15 @@ config EDD
           obscure configurations. Most disk controller BIOS vendors do
           not yet implement this feature.
 
+config EDD_OFF
+       bool "Sets default behavior for EDD detection to off"
+       depends on EDD
+       default n
+       help
+         Say Y if you want EDD disabled by default, even though it is compiled into the
+         kernel. Say N if you want EDD enabled by default. EDD can be dynamically set
+         using the kernel parameter 'edd={on|skipmbr|off}'.
+
 config EFI_VARS
        tristate "EFI Variable Support via sysfs"
        depends on EFI
index f235940719e71363b0a5f273ac84e9bc57093c37..25918f7dfd0fe73884ff86101ed90c04346e00cb 100644 (file)
@@ -63,7 +63,7 @@ static void smi_data_buf_free(void)
                return;
 
        dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
-               __FUNCTION__, smi_data_buf_phys_addr, smi_data_buf_size);
+               __func__, smi_data_buf_phys_addr, smi_data_buf_size);
 
        dma_free_coherent(&dcdbas_pdev->dev, smi_data_buf_size, smi_data_buf,
                          smi_data_buf_handle);
@@ -92,7 +92,7 @@ static int smi_data_buf_realloc(unsigned long size)
        if (!buf) {
                dev_dbg(&dcdbas_pdev->dev,
                        "%s: failed to allocate memory size %lu\n",
-                       __FUNCTION__, size);
+                       __func__, size);
                return -ENOMEM;
        }
        /* memory zeroed by dma_alloc_coherent */
@@ -110,7 +110,7 @@ static int smi_data_buf_realloc(unsigned long size)
        smi_data_buf_size = size;
 
        dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n",
-               __FUNCTION__, smi_data_buf_phys_addr, smi_data_buf_size);
+               __func__, smi_data_buf_phys_addr, smi_data_buf_size);
 
        return 0;
 }
@@ -258,7 +258,7 @@ static int smi_request(struct smi_cmd *smi_cmd)
 
        if (smi_cmd->magic != SMI_CMD_MAGIC) {
                dev_info(&dcdbas_pdev->dev, "%s: invalid magic value\n",
-                        __FUNCTION__);
+                        __func__);
                return -EBADR;
        }
 
@@ -267,7 +267,7 @@ static int smi_request(struct smi_cmd *smi_cmd)
        set_cpus_allowed_ptr(current, &cpumask_of_cpu(0));
        if (smp_processor_id() != 0) {
                dev_dbg(&dcdbas_pdev->dev, "%s: failed to get CPU 0\n",
-                       __FUNCTION__);
+                       __func__);
                ret = -EBUSY;
                goto out;
        }
@@ -428,7 +428,7 @@ static int host_control_smi(void)
 
        default:
                dev_dbg(&dcdbas_pdev->dev, "%s: invalid SMI type %u\n",
-                       __FUNCTION__, host_control_smi_type);
+                       __func__, host_control_smi_type);
                return -ENOSYS;
        }
 
@@ -456,13 +456,13 @@ static void dcdbas_host_control(void)
        host_control_action = HC_ACTION_NONE;
 
        if (!smi_data_buf) {
-               dev_dbg(&dcdbas_pdev->dev, "%s: no SMI buffer\n", __FUNCTION__);
+               dev_dbg(&dcdbas_pdev->dev, "%s: no SMI buffer\n", __func__);
                return;
        }
 
        if (smi_data_buf_size < sizeof(struct apm_cmd)) {
                dev_dbg(&dcdbas_pdev->dev, "%s: SMI buffer too small\n",
-                       __FUNCTION__);
+                       __func__);
                return;
        }
 
index 477a3d0e3caf83ccffb2cf472375cafcc799733e..6a8b1e037e0776e7e4a1e3d1214380e062da694c 100644 (file)
@@ -123,7 +123,7 @@ static int create_packet(void *data, size_t length)
        if (!newpacket) {
                printk(KERN_WARNING
                        "dell_rbu:%s: failed to allocate new "
-                       "packet\n", __FUNCTION__);
+                       "packet\n", __func__);
                retval = -ENOMEM;
                spin_lock(&rbu_data.lock);
                goto out_noalloc;
@@ -152,7 +152,7 @@ static int create_packet(void *data, size_t length)
                printk(KERN_WARNING
                        "dell_rbu:%s: failed to allocate "
                        "invalid_addr_packet_array \n",
-                       __FUNCTION__);
+                       __func__);
                retval = -ENOMEM;
                spin_lock(&rbu_data.lock);
                goto out_alloc_packet;
@@ -164,7 +164,7 @@ static int create_packet(void *data, size_t length)
                if (!packet_data_temp_buf) {
                        printk(KERN_WARNING
                                "dell_rbu:%s: failed to allocate new "
-                               "packet\n", __FUNCTION__);
+                               "packet\n", __func__);
                        retval = -ENOMEM;
                        spin_lock(&rbu_data.lock);
                        goto out_alloc_packet_array;
@@ -416,7 +416,7 @@ static int img_update_realloc(unsigned long size)
                 */
                if ((size != 0) && (rbu_data.image_update_buffer == NULL)) {
                        printk(KERN_ERR "dell_rbu:%s: corruption "
-                               "check failed\n", __FUNCTION__);
+                               "check failed\n", __func__);
                        return -EINVAL;
                }
                /*
@@ -642,7 +642,7 @@ static ssize_t write_rbu_image_type(struct kobject *kobj,
                        if (req_firm_rc) {
                                printk(KERN_ERR
                                        "dell_rbu:%s request_firmware_nowait"
-                                       " failed %d\n", __FUNCTION__, rc);
+                                       " failed %d\n", __func__, rc);
                                rc = -EIO;
                        } else
                                rbu_data.entry_created = 1;
@@ -718,7 +718,7 @@ static int __init dcdrbu_init(void)
        if (IS_ERR(rbu_device)) {
                printk(KERN_ERR
                        "dell_rbu:%s:platform_device_register_simple "
-                       "failed\n", __FUNCTION__);
+                       "failed\n", __func__);
                return PTR_ERR(rbu_device);
        }
 
index 24c62b848bf976dea7eabd0c48684e561d0d29cc..7f138c6195ff38ceba44bf14dea45a83705c47d4 100644 (file)
@@ -382,7 +382,7 @@ fail:
        spin_unlock_irqrestore(&gpio_lock, flags);
        if (status)
                pr_debug("%s: gpio-%d status %d\n",
-                       __FUNCTION__, gpio, status);
+                       __func__, gpio, status);
        return status;
 }
 EXPORT_SYMBOL_GPL(gpio_direction_input);
@@ -420,7 +420,7 @@ fail:
        spin_unlock_irqrestore(&gpio_lock, flags);
        if (status)
                pr_debug("%s: gpio-%d status %d\n",
-                       __FUNCTION__, gpio, status);
+                       __func__, gpio, status);
        return status;
 }
 EXPORT_SYMBOL_GPL(gpio_direction_output);
index e0e0af5361083e6cd9483b971ff427cab43dad80..5a99e81d27843c8ce9e376684196b5daa253f90a 100644 (file)
 #define PCA953X_INVERT         2
 #define PCA953X_DIRECTION      3
 
-/* This is temporary - in 2.6.26 i2c_driver_data should replace it. */
-struct pca953x_desc {
-       char            name[I2C_NAME_SIZE];
-       unsigned long   driver_data;
-};
-
-static const struct pca953x_desc pca953x_descs[] = {
+static const struct i2c_device_id pca953x_id[] = {
        { "pca9534", 8, },
        { "pca9535", 16, },
        { "pca9536", 4, },
@@ -37,7 +31,9 @@ static const struct pca953x_desc pca953x_descs[] = {
        { "pca9538", 8, },
        { "pca9539", 16, },
        /* REVISIT several pca955x parts should work here too */
+       { }
 };
+MODULE_DEVICE_TABLE(i2c, pca953x_id);
 
 struct pca953x_chip {
        unsigned gpio_start;
@@ -192,26 +188,17 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
        gc->owner = THIS_MODULE;
 }
 
-static int __devinit pca953x_probe(struct i2c_client *client)
+static int __devinit pca953x_probe(struct i2c_client *client,
+                                  const struct i2c_device_id *id)
 {
        struct pca953x_platform_data *pdata;
        struct pca953x_chip *chip;
        int ret, i;
-       const struct pca953x_desc *id = NULL;
 
        pdata = client->dev.platform_data;
        if (pdata == NULL)
                return -ENODEV;
 
-       /* this loop vanishes when we get i2c_device_id */
-       for (i = 0; i < ARRAY_SIZE(pca953x_descs); i++)
-               if (!strcmp(pca953x_descs[i].name, client->name)) {
-                       id = pca953x_descs + i;
-                       break;
-               }
-       if (!id)
-               return -ENODEV;
-
        chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
        if (chip == NULL)
                return -ENOMEM;
@@ -291,6 +278,7 @@ static struct i2c_driver pca953x_driver = {
        },
        .probe          = pca953x_probe,
        .remove         = pca953x_remove,
+       .id_table       = pca953x_id,
 };
 
 static int __init pca953x_init(void)
index 1106aa15ac79ad92d6807aab7a0aa2106e786784..aa6cc8b2a2bc88afbeca4dec1b67bc75c05288a0 100644 (file)
 #include <asm/gpio.h>
 
 
+static const struct i2c_device_id pcf857x_id[] = {
+       { "pcf8574", 8 },
+       { "pca8574", 8 },
+       { "pca9670", 8 },
+       { "pca9672", 8 },
+       { "pca9674", 8 },
+       { "pcf8575", 16 },
+       { "pca8575", 16 },
+       { "pca9671", 16 },
+       { "pca9673", 16 },
+       { "pca9675", 16 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, pcf857x_id);
+
 /*
  * The pcf857x, pca857x, and pca967x chips only expose one read and one
  * write register.  Writing a "one" bit (to match the reset state) lets
@@ -142,7 +157,8 @@ static void pcf857x_set16(struct gpio_chip *chip, unsigned offset, int value)
 
 /*-------------------------------------------------------------------------*/
 
-static int pcf857x_probe(struct i2c_client *client)
+static int pcf857x_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
 {
        struct pcf857x_platform_data    *pdata;
        struct pcf857x                  *gpio;
@@ -172,13 +188,8 @@ static int pcf857x_probe(struct i2c_client *client)
         *
         * NOTE: we don't distinguish here between *4 and *4a parts.
         */
-       if (strcmp(client->name, "pcf8574") == 0
-                       || strcmp(client->name, "pca8574") == 0
-                       || strcmp(client->name, "pca9670") == 0
-                       || strcmp(client->name, "pca9672") == 0
-                       || strcmp(client->name, "pca9674") == 0
-                       ) {
-               gpio->chip.ngpio = 8;
+       gpio->chip.ngpio = id->driver_data;
+       if (gpio->chip.ngpio == 8) {
                gpio->chip.direction_input = pcf857x_input8;
                gpio->chip.get = pcf857x_get8;
                gpio->chip.direction_output = pcf857x_output8;
@@ -198,13 +209,7 @@ static int pcf857x_probe(struct i2c_client *client)
         *
         * NOTE: we don't distinguish here between '75 and '75c parts.
         */
-       } else if (strcmp(client->name, "pcf8575") == 0
-                       || strcmp(client->name, "pca8575") == 0
-                       || strcmp(client->name, "pca9671") == 0
-                       || strcmp(client->name, "pca9673") == 0
-                       || strcmp(client->name, "pca9675") == 0
-                       ) {
-               gpio->chip.ngpio = 16;
+       } else if (gpio->chip.ngpio == 16) {
                gpio->chip.direction_input = pcf857x_input16;
                gpio->chip.get = pcf857x_get16;
                gpio->chip.direction_output = pcf857x_output16;
@@ -313,6 +318,7 @@ static struct i2c_driver pcf857x_driver = {
        },
        .probe  = pcf857x_probe,
        .remove = pcf857x_remove,
+       .id_table = pcf857x_id,
 };
 
 static int __init pcf857x_init(void)
index e03c67dd3e6325ae186fbe7ecc9523223f3015ad..f43d6d3cf2fa2429d5689bbe05e87cf0f99358e0 100644 (file)
@@ -606,7 +606,7 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
                case 2:
                        if ((end - start) < 2)
                                return NULL;
-                       item->data.u16 = le16_to_cpu(get_unaligned((__le16*)start));
+                       item->data.u16 = get_unaligned_le16(start);
                        start = (__u8 *)((__le16 *)start + 1);
                        return start;
 
@@ -614,7 +614,7 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
                        item->size++;
                        if ((end - start) < 4)
                                return NULL;
-                       item->data.u32 = le32_to_cpu(get_unaligned((__le32*)start));
+                       item->data.u32 = get_unaligned_le32(start);
                        start = (__u8 *)((__le32 *)start + 1);
                        return start;
        }
@@ -765,7 +765,7 @@ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
 
        report += offset >> 3;  /* adjust byte index */
        offset &= 7;            /* now only need bit offset into one byte */
-       x = le64_to_cpu(get_unaligned((__le64 *) report));
+       x = get_unaligned_le64(report);
        x = (x >> offset) & ((1ULL << n) - 1);  /* extract bit field */
        return (u32) x;
 }
index ed71a8bc70dcf855710d525aedff131965c57122..5c8b6e0ff47c21354592d6ddcb63f5ebe48db5db 100644 (file)
@@ -224,7 +224,7 @@ static int ads7828_detect(struct i2c_adapter *adapter, int address, int kind)
                        if (in_data & 0xF000) {
                                printk(KERN_DEBUG
                                "%s : Doesn't look like an ads7828 device\n",
-                               __FUNCTION__);
+                               __func__);
                                goto exit_free;
                        }
                }
index 1464338e4e11b891298ff18f212bf2135c17804a..dc1f30e432eab96864d52af0706a2ac39f7338a7 100644 (file)
@@ -117,7 +117,8 @@ struct f75375_data {
 static int f75375_attach_adapter(struct i2c_adapter *adapter);
 static int f75375_detect(struct i2c_adapter *adapter, int address, int kind);
 static int f75375_detach_client(struct i2c_client *client);
-static int f75375_probe(struct i2c_client *client);
+static int f75375_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id);
 static int f75375_remove(struct i2c_client *client);
 
 static struct i2c_driver f75375_legacy_driver = {
@@ -128,12 +129,20 @@ static struct i2c_driver f75375_legacy_driver = {
        .detach_client = f75375_detach_client,
 };
 
+static const struct i2c_device_id f75375_id[] = {
+       { "f75373", f75373 },
+       { "f75375", f75375 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, f75375_id);
+
 static struct i2c_driver f75375_driver = {
        .driver = {
                .name = "f75375",
        },
        .probe = f75375_probe,
        .remove = f75375_remove,
+       .id_table = f75375_id,
 };
 
 static inline int f75375_read8(struct i2c_client *client, u8 reg)
@@ -628,7 +637,8 @@ static void f75375_init(struct i2c_client *client, struct f75375_data *data,
 
 }
 
-static int f75375_probe(struct i2c_client *client)
+static int f75375_probe(struct i2c_client *client,
+               const struct i2c_device_id *id)
 {
        struct f75375_data *data = i2c_get_clientdata(client);
        struct f75375s_platform_data *f75375s_pdata = client->dev.platform_data;
@@ -643,15 +653,7 @@ static int f75375_probe(struct i2c_client *client)
        i2c_set_clientdata(client, data);
        data->client = client;
        mutex_init(&data->update_lock);
-
-       if (strcmp(client->name, "f75375") == 0)
-               data->kind = f75375;
-       else if (strcmp(client->name, "f75373") == 0)
-               data->kind = f75373;
-       else {
-               dev_err(&client->dev, "Unsupported device: %s\n", client->name);
-               return -ENODEV;
-       }
+       data->kind = id->driver_data;
 
        if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group)))
                goto exit_free;
@@ -712,6 +714,7 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind)
        u8 version = 0;
        int err = 0;
        const char *name = "";
+       struct i2c_device_id id;
 
        if (!(client = kzalloc(sizeof(*client), GFP_KERNEL))) {
                err = -ENOMEM;
@@ -748,7 +751,9 @@ static int f75375_detect(struct i2c_adapter *adapter, int address, int kind)
        if ((err = i2c_attach_client(client)))
                goto exit_free;
 
-       if ((err = f75375_probe(client)) < 0)
+       strlcpy(id.name, name, I2C_NAME_SIZE);
+       id.driver_data = kind;
+       if ((err = f75375_probe(client, &id)) < 0)
                goto exit_detach;
 
        return 0;
index e5e96c8175660b15f006d9517a2866248e5a4a62..c38a0a112208286787d94966f57048980ad459b8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * i2c-amd756-s4882.c - i2c-amd756 extras for the Tyan S4882 motherboard
  *
- * Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2004, 2008 Jean Delvare <khali@linux-fr.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
@@ -231,7 +231,8 @@ ERROR2:
        kfree(s4882_adapter);
        s4882_adapter = NULL;
 ERROR1:
-       i2c_del_adapter(&amd756_smbus);
+       /* Restore physical bus */
+       i2c_add_adapter(&amd756_smbus);
 ERROR0:
        return error;
 }
index 9bbe96cef719ee204243645e52b124323d2721f7..fdc9ad805e358528b8599f0dbd4635bb817155e7 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/ioport.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
-#include <linux/apm_bios.h>
 #include <linux/dmi.h>
 #include <asm/io.h>
 
@@ -223,7 +222,7 @@ static int piix4_transaction(void)
                        dev_err(&piix4_adapter.dev, "Failed! (%02x)\n", temp);
                        return -1;
                } else {
-                       dev_dbg(&piix4_adapter.dev, "Successfull!\n");
+                       dev_dbg(&piix4_adapter.dev, "Successful!\n");
                }
        }
 
@@ -343,12 +342,7 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
 
 
        switch (size) {
-       case PIIX4_BYTE:        /* Where is the result put? I assume here it is in
-                                  SMBHSTDAT0 but it might just as well be in the
-                                  SMBHSTCMD. No clue in the docs */
-
-               data->byte = inb_p(SMBHSTDAT0);
-               break;
+       case PIIX4_BYTE:
        case PIIX4_BYTE_DATA:
                data->byte = inb_p(SMBHSTDAT0);
                break;
index 283769cecee297531fd80c66e1cc34f1ee1bbf64..9ca8f9155f958c40378a50770eb3327a0702c2e6 100644 (file)
@@ -238,7 +238,7 @@ static int sis5595_transaction(struct i2c_adapter *adap)
                        dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
                        return -1;
                } else {
-                       dev_dbg(&adap->dev, "Successfull!\n");
+                       dev_dbg(&adap->dev, "Successful!\n");
                }
        }
 
@@ -316,14 +316,8 @@ static s32 sis5595_access(struct i2c_adapter *adap, u16 addr,
                }
                size = (size == I2C_SMBUS_PROC_CALL) ? SIS5595_PROC_CALL : SIS5595_WORD_DATA;
                break;
-/*
-       case I2C_SMBUS_BLOCK_DATA:
-               printk(KERN_WARNING "sis5595.o: Block data not yet implemented!\n");
-               return -1;
-               break;
-*/
        default:
-               printk(KERN_WARNING "sis5595.o: Unsupported transaction %d\n", size);
+               dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
                return -1;
        }
 
@@ -338,9 +332,7 @@ static s32 sis5595_access(struct i2c_adapter *adap, u16 addr,
 
 
        switch (size) {
-       case SIS5595_BYTE:      /* Where is the result put? I assume here it is in
-                                  SMB_DATA but it might just as well be in the
-                                  SMB_CMD. No clue in the docs */
+       case SIS5595_BYTE:
        case SIS5595_BYTE_DATA:
                data->byte = sis5595_read(SMB_BYTE);
                break;
index 5fd734f99ee9df9f12ff5103fa13606c557d852f..3765dd7f450f06e7c71f6623d67795c9e4cc056d 100644 (file)
@@ -136,7 +136,7 @@ static int sis630_transaction_start(struct i2c_adapter *adap, int size, u8 *oldc
                        dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
                        return -1;
                 } else {
-                       dev_dbg(&adap->dev, "Successfull!\n");
+                       dev_dbg(&adap->dev, "Successful!\n");
                }
         }
 
index c2a9f8c94f5e0363cc71580b271010125e3ada00..d08eeec53913ce9759a74e82b984bdc06dcf18b8 100644 (file)
@@ -33,7 +33,7 @@
 static unsigned short chip_addr[MAX_CHIPS];
 module_param_array(chip_addr, ushort, NULL, S_IRUGO);
 MODULE_PARM_DESC(chip_addr,
-                "Chip addresses (up to 10, between 0x03 and 0x77)\n");
+                "Chip addresses (up to 10, between 0x03 and 0x77)");
 
 struct stub_chip {
        u8 pointer;
index 1b0cfd5472fda700c4e123edf834f2f6f20541ec..de9db49e54d93d8785f0beef0df4c5df28036a12 100644 (file)
@@ -51,7 +51,6 @@ struct taos_data {
 /* TAOS TSL2550 EVM */
 static struct i2c_board_info tsl2550_info = {
        I2C_BOARD_INFO("tsl2550", 0x39),
-       .type   = "tsl2550",
 };
 
 /* Instantiate i2c devices based on the adapter name */
@@ -59,7 +58,7 @@ static struct i2c_client *taos_instantiate_device(struct i2c_adapter *adapter)
 {
        if (!strncmp(adapter->name, "TAOS TSL2550 EVM", 16)) {
                dev_info(&adapter->dev, "Instantiating device %s at 0x%02x\n",
-                       tsl2550_info.driver_name, tsl2550_info.addr);
+                       tsl2550_info.type, tsl2550_info.addr);
                return i2c_new_device(adapter, &tsl2550_info);
        }
 
index 9e94542c18a2bc57abd22d05c17c0b04955fe7c3..23be4d42cb02c48da998864f3d13da047e75092b 100644 (file)
@@ -200,7 +200,8 @@ static struct bin_attribute ds1682_eeprom_attr = {
 /*
  * Called when a ds1682 device is matched with this driver
  */
-static int ds1682_probe(struct i2c_client *client)
+static int ds1682_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
 {
        int rc;
 
@@ -234,12 +235,19 @@ static int ds1682_remove(struct i2c_client *client)
        return 0;
 }
 
+static const struct i2c_device_id ds1682_id[] = {
+       { "ds1682", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, ds1682_id);
+
 static struct i2c_driver ds1682_driver = {
        .driver = {
                .name = "ds1682",
        },
        .probe = ds1682_probe,
        .remove = ds1682_remove,
+       .id_table = ds1682_id,
 };
 
 static int __init ds1682_init(void)
index 2dea0123a958577ad87a3095c159edf177d7050e..b36db1797c11138982171b421c45a325bab01a62 100644 (file)
@@ -1149,7 +1149,8 @@ static inline void menelaus_rtc_init(struct menelaus_chip *m)
 
 static struct i2c_driver menelaus_i2c_driver;
 
-static int menelaus_probe(struct i2c_client *client)
+static int menelaus_probe(struct i2c_client *client,
+                         const struct i2c_device_id *id)
 {
        struct menelaus_chip    *menelaus;
        int                     rev = 0, val;
@@ -1242,12 +1243,19 @@ static int __exit menelaus_remove(struct i2c_client *client)
        return 0;
 }
 
+static const struct i2c_device_id menelaus_id[] = {
+       { "menelaus", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, menelaus_id);
+
 static struct i2c_driver menelaus_i2c_driver = {
        .driver = {
                .name           = DRIVER_NAME,
        },
        .probe          = menelaus_probe,
        .remove         = __exit_p(menelaus_remove),
+       .id_table       = menelaus_id,
 };
 
 static int __init menelaus_init(void)
index b67f69c2e7f3850c9a80cf405dc78a3b29505d93..85949685191bb3218e75cb5547aab3750b7e291d 100644 (file)
@@ -64,7 +64,6 @@ static struct i2c_driver tps65010_driver;
  * as part of board setup by a bootloader.
  */
 enum tps_model {
-       TPS_UNKNOWN = 0,
        TPS65010,
        TPS65011,
        TPS65012,
@@ -527,11 +526,13 @@ static int __exit tps65010_remove(struct i2c_client *client)
        flush_scheduled_work();
        debugfs_remove(tps->file);
        kfree(tps);
+       i2c_set_clientdata(client, NULL);
        the_tps = NULL;
        return 0;
 }
 
-static int tps65010_probe(struct i2c_client *client)
+static int tps65010_probe(struct i2c_client *client,
+                         const struct i2c_device_id *id)
 {
        struct tps65010         *tps;
        int                     status;
@@ -552,20 +553,7 @@ static int tps65010_probe(struct i2c_client *client)
        mutex_init(&tps->lock);
        INIT_DELAYED_WORK(&tps->work, tps65010_work);
        tps->client = client;
-
-       if (strcmp(client->name, "tps65010") == 0)
-               tps->model = TPS65010;
-       else if (strcmp(client->name, "tps65011") == 0)
-               tps->model = TPS65011;
-       else if (strcmp(client->name, "tps65012") == 0)
-               tps->model = TPS65012;
-       else if (strcmp(client->name, "tps65013") == 0)
-               tps->model = TPS65013;
-       else {
-               dev_warn(&client->dev, "unknown chip '%s'\n", client->name);
-               status = -ENODEV;
-               goto fail1;
-       }
+       tps->model = id->driver_data;
 
        /* the IRQ is active low, but many gpio lines can't support that
         * so this driver uses falling-edge triggers instead.
@@ -594,9 +582,6 @@ static int tps65010_probe(struct i2c_client *client)
        case TPS65012:
                tps->por = 1;
                break;
-       case TPS_UNKNOWN:
-               printk(KERN_WARNING "%s: unknown TPS chip\n", DRIVER_NAME);
-               break;
        /* else CHGCONFIG.POR is replaced by AUA, enabling a WAIT mode */
        }
        tps->chgconf = i2c_smbus_read_byte_data(client, TPS_CHGCONFIG);
@@ -615,6 +600,7 @@ static int tps65010_probe(struct i2c_client *client)
                i2c_smbus_read_byte_data(client, TPS_DEFGPIO),
                i2c_smbus_read_byte_data(client, TPS_MASK3));
 
+       i2c_set_clientdata(client, tps);
        the_tps = tps;
 
 #if    defined(CONFIG_USB_GADGET) && !defined(CONFIG_USB_OTG)
@@ -682,12 +668,22 @@ fail1:
        return status;
 }
 
+static const struct i2c_device_id tps65010_id[] = {
+       { "tps65010", TPS65010 },
+       { "tps65011", TPS65011 },
+       { "tps65012", TPS65012 },
+       { "tps65013", TPS65013 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, tps65010_id);
+
 static struct i2c_driver tps65010_driver = {
        .driver = {
                .name   = "tps65010",
        },
        .probe  = tps65010_probe,
        .remove = __exit_p(tps65010_remove),
+       .id_table = tps65010_id,
 };
 
 /*-------------------------------------------------------------------------*/
index a10fd2791a69ab938eb214bd2376a02c76749959..1a9cc135219f4a5ea613c8da9819676cf19da0f4 100644 (file)
@@ -364,7 +364,8 @@ static int tsl2550_init_client(struct i2c_client *client)
  */
 
 static struct i2c_driver tsl2550_driver;
-static int __devinit tsl2550_probe(struct i2c_client *client)
+static int __devinit tsl2550_probe(struct i2c_client *client,
+                                  const struct i2c_device_id *id)
 {
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
        struct tsl2550_data *data;
@@ -451,6 +452,12 @@ static int tsl2550_resume(struct i2c_client *client)
 
 #endif /* CONFIG_PM */
 
+static const struct i2c_device_id tsl2550_id[] = {
+       { "tsl2550", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, tsl2550_id);
+
 static struct i2c_driver tsl2550_driver = {
        .driver = {
                .name   = TSL2550_DRV_NAME,
@@ -460,6 +467,7 @@ static struct i2c_driver tsl2550_driver = {
        .resume = tsl2550_resume,
        .probe  = tsl2550_probe,
        .remove = __devexit_p(tsl2550_remove),
+       .id_table = tsl2550_id,
 };
 
 static int __init tsl2550_init(void)
index 6c7fa8d53c0eeaeccfec0366302cdc37717efecb..26384daccb968180c369207e70f35e0a3598e04d 100644 (file)
@@ -48,6 +48,17 @@ static DEFINE_IDR(i2c_adapter_idr);
 
 /* ------------------------------------------------------------------------- */
 
+static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
+                                               const struct i2c_client *client)
+{
+       while (id->name[0]) {
+               if (strcmp(client->name, id->name) == 0)
+                       return id;
+               id++;
+       }
+       return NULL;
+}
+
 static int i2c_device_match(struct device *dev, struct device_driver *drv)
 {
        struct i2c_client       *client = to_i2c_client(dev);
@@ -59,6 +70,10 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)
        if (!is_newstyle_driver(driver))
                return 0;
 
+       /* match on an id table if there is one */
+       if (driver->id_table)
+               return i2c_match_id(driver->id_table, client) != NULL;
+
        /* new style drivers use the same kind of driver matching policy
         * as platform devices or SPI:  compare device and driver IDs.
         */
@@ -73,11 +88,17 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
        struct i2c_client       *client = to_i2c_client(dev);
 
        /* by definition, legacy drivers can't hotplug */
-       if (dev->driver || !client->driver_name)
+       if (dev->driver)
                return 0;
 
-       if (add_uevent_var(env, "MODALIAS=%s", client->driver_name))
-               return -ENOMEM;
+       if (client->driver_name[0]) {
+               if (add_uevent_var(env, "MODALIAS=%s", client->driver_name))
+                       return -ENOMEM;
+       } else {
+               if (add_uevent_var(env, "MODALIAS=%s%s",
+                                  I2C_MODULE_PREFIX, client->name))
+                       return -ENOMEM;
+       }
        dev_dbg(dev, "uevent\n");
        return 0;
 }
@@ -90,13 +111,19 @@ static int i2c_device_probe(struct device *dev)
 {
        struct i2c_client       *client = to_i2c_client(dev);
        struct i2c_driver       *driver = to_i2c_driver(dev->driver);
+       const struct i2c_device_id *id;
        int status;
 
        if (!driver->probe)
                return -ENODEV;
        client->driver = driver;
        dev_dbg(dev, "probe\n");
-       status = driver->probe(client);
+
+       if (driver->id_table)
+               id = i2c_match_id(driver->id_table, client);
+       else
+               id = NULL;
+       status = driver->probe(client, id);
        if (status)
                client->driver = NULL;
        return status;
@@ -179,9 +206,9 @@ static ssize_t show_client_name(struct device *dev, struct device_attribute *att
 static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct i2c_client *client = to_i2c_client(dev);
-       return client->driver_name
+       return client->driver_name[0]
                ? sprintf(buf, "%s\n", client->driver_name)
-               : 0;
+               : sprintf(buf, "%s%s\n", I2C_MODULE_PREFIX, client->name);
 }
 
 static struct device_attribute i2c_dev_attrs[] = {
@@ -300,15 +327,21 @@ void i2c_unregister_device(struct i2c_client *client)
 EXPORT_SYMBOL_GPL(i2c_unregister_device);
 
 
-static int dummy_nop(struct i2c_client *client)
+static int dummy_probe(struct i2c_client *client,
+                      const struct i2c_device_id *id)
+{
+       return 0;
+}
+
+static int dummy_remove(struct i2c_client *client)
 {
        return 0;
 }
 
 static struct i2c_driver dummy_driver = {
        .driver.name    = "dummy",
-       .probe          = dummy_nop,
-       .remove         = dummy_nop,
+       .probe          = dummy_probe,
+       .remove         = dummy_remove,
 };
 
 /**
index fe9df38f62cc3e4ab877798e695d741f1b3457d0..68e7f19dc03662b405363ca23bf0081db73baa4a 100644 (file)
@@ -782,7 +782,7 @@ static ide_startstop_t cdrom_start_seek_continuation(ide_drive_t *drive)
 
        sector_div(frame, queue_hardsect_size(drive->queue) >> SECTOR_BITS);
 
-       memset(rq->cmd, 0, sizeof(rq->cmd));
+       memset(rq->cmd, 0, BLK_MAX_CDB);
        rq->cmd[0] = GPCMD_SEEK;
        put_unaligned(cpu_to_be32(frame), (unsigned int *) &rq->cmd[2]);
 
@@ -1694,7 +1694,7 @@ static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq)
        long block = (long)rq->hard_sector / (hard_sect >> 9);
        unsigned long blocks = rq->hard_nr_sectors / (hard_sect >> 9);
 
-       memset(rq->cmd, 0, sizeof(rq->cmd));
+       memset(rq->cmd, 0, BLK_MAX_CDB);
 
        if (rq_data_dir(rq) == READ)
                rq->cmd[0] = GPCMD_READ_10;
index 6ed7ca0713311ca1eed5ac06c9abd1dbdff0105d..6490a2dea96b01526657615ceb7139d9b1603a55 100644 (file)
@@ -326,7 +326,7 @@ void ide_cd_log_error(const char *name, struct request *failed_command,
 
                printk(KERN_ERR "  The failed \"%s\" packet command "
                                "was: \n  \"", s);
-               for (i = 0; i < sizeof(failed_command->cmd); i++)
+               for (i = 0; i < BLK_MAX_CDB; i++)
                        printk(KERN_CONT "%02x ", failed_command->cmd[i]);
                printk(KERN_CONT "\"\n");
        }
index 788783da9025804eb5af6e6f02134f7efbd411ba..696525342e9a56977c1d2ac88d72497be5a7e866 100644 (file)
@@ -1550,8 +1550,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
 
 void ide_init_drive_cmd (struct request *rq)
 {
-       memset(rq, 0, sizeof(*rq));
-       rq->ref_count = 1;
+       blk_rq_init(NULL, rq);
 }
 
 EXPORT_SYMBOL(ide_init_drive_cmd);
index 7b2f3815a838700bfdce5d88ea62f0d6199037d7..8d6ad812a014e3e4a5ea3c1611874d550e3d4bf1 100644 (file)
@@ -822,6 +822,7 @@ static int ide_drivers_open(struct inode *inode, struct file *file)
 }
 
 static const struct file_operations ide_drivers_operations = {
+       .owner          = THIS_MODULE,
        .open           = ide_drivers_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -830,16 +831,12 @@ static const struct file_operations ide_drivers_operations = {
 
 void proc_ide_create(void)
 {
-       struct proc_dir_entry *entry;
-
        proc_ide_root = proc_mkdir("ide", NULL);
 
        if (!proc_ide_root)
                return;
 
-       entry = create_proc_entry("drivers", 0, proc_ide_root);
-       if (entry)
-               entry->proc_fops = &ide_drivers_operations;
+       proc_create("drivers", 0, proc_ide_root, &ide_drivers_operations);
 }
 
 void proc_ide_destroy(void)
index 54a43b0446081fdc2e38887aa3b296e0bbbb14f8..1e1f26331a24dd2c4aa3bc0028c216cd6f1c2c40 100644 (file)
@@ -662,7 +662,7 @@ static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc)
 
 static void idetape_init_rq(struct request *rq, u8 cmd)
 {
-       memset(rq, 0, sizeof(*rq));
+       blk_rq_init(NULL, rq);
        rq->cmd_type = REQ_TYPE_SPECIAL;
        rq->cmd[0] = cmd;
 }
index 9a846a0cd5a462c01e403069fef737d745dce88c..0c908ca3ff79654ac3d0bf8fe500f32658d84016 100644 (file)
@@ -494,8 +494,7 @@ int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *task, u8 *buf, u16 nsect)
 {
        struct request rq;
 
-       memset(&rq, 0, sizeof(rq));
-       rq.ref_count = 1;
+       blk_rq_init(NULL, &rq);
        rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
        rq.buffer = buf;
 
index 999584c03d9766d8bd1a9b083167e23e2cb39965..c758dcb13b14209a97bfdca02ef056ee113712a7 100644 (file)
@@ -564,7 +564,7 @@ static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
        if (!(drive->dn % 2))
                ide_acpi_get_timing(hwif);
 
-       memset(&rq, 0, sizeof(rq));
+       blk_rq_init(NULL, &rq);
        memset(&rqpm, 0, sizeof(rqpm));
        memset(&args, 0, sizeof(args));
        rq.cmd_type = REQ_TYPE_PM_SUSPEND;
@@ -602,7 +602,7 @@ static int generic_ide_resume(struct device *dev)
 
        ide_acpi_exec_tfs(drive);
 
-       memset(&rq, 0, sizeof(rq));
+       blk_rq_init(NULL, &rq);
        memset(&rqpm, 0, sizeof(rqpm));
        memset(&args, 0, sizeof(args));
        rq.cmd_type = REQ_TYPE_PM_RESUME;
index b36a22b8c213807a1966595eafc68adf463a75ba..c1922f9cfe80606e82a1ca2f38ae12e42877fc18 100644 (file)
@@ -412,14 +412,14 @@ static u8 __devinit ali_cable_detect(ide_hwif_t *hwif)
        return cbl;
 }
 
-#ifndef CONFIG_SPARC64
+#if !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC)
 /**
  *     init_hwif_ali15x3       -       Initialize the ALI IDE x86 stuff
  *     @hwif: interface to configure
  *
  *     Obtain the IRQ tables for an ALi based IDE solution on the PC
  *     class platforms. This part of the code isn't applicable to the
- *     Sparc systems
+ *     Sparc and PowerPC systems.
  */
 
 static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
@@ -463,7 +463,9 @@ static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
                        hwif->irq = irq;
        }
 }
-#endif
+#else
+#define init_hwif_ali15x3 NULL
+#endif /* !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC) */
 
 /**
  *     init_dma_ali15x3        -       set up DMA on ALi15x3
@@ -517,9 +519,7 @@ static const struct ide_dma_ops ali_dma_ops = {
 static const struct ide_port_info ali15x3_chipset __devinitdata = {
        .name           = "ALI15X3",
        .init_chipset   = init_chipset_ali15x3,
-#ifndef CONFIG_SPARC64
        .init_hwif      = init_hwif_ali15x3,
-#endif
        .init_dma       = init_dma_ali15x3,
        .port_ops       = &ali_port_ops,
        .pio_mask       = ATA_PIO5,
index 4cf8fc54aa2a109d8547f9ce70de9325b4508f1e..0006b9e58567b7d595de4253b6d67e4a78f12d8f 100644 (file)
@@ -737,8 +737,15 @@ static const struct ide_port_ops sil_sata_port_ops = {
        .cable_detect           = sil_cable_detect,
 };
 
-static struct ide_dma_ops sil_dma_ops = {
+static const struct ide_dma_ops sil_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ide_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = ide_dma_start,
+       .dma_end                = __ide_dma_end,
        .dma_test_irq           = siimage_dma_test_irq,
+       .dma_timeout            = ide_dma_timeout,
+       .dma_lost_irq           = ide_dma_lost_irq,
 };
 
 #define DECLARE_SII_DEV(name_str, p_ops)               \
index 4e3128ff73c135ce988cdbb9d75fd58981faa26b..fe78f7d250991d120adcbf6c93c50b0ee38078c7 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/sched.h>
 #include <linux/hugetlb.h>
+#include <linux/dma-attrs.h>
 
 #include "uverbs.h"
 
@@ -72,9 +73,10 @@ static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int d
  * @addr: userspace virtual address to start at
  * @size: length of region to pin
  * @access: IB_ACCESS_xxx flags for memory being pinned
+ * @dmasync: flush in-flight DMA when the memory region is written
  */
 struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
-                           size_t size, int access)
+                           size_t size, int access, int dmasync)
 {
        struct ib_umem *umem;
        struct page **page_list;
@@ -87,6 +89,10 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
        int ret;
        int off;
        int i;
+       DEFINE_DMA_ATTRS(attrs);
+
+       if (dmasync)
+               dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs);
 
        if (!can_do_mlock())
                return ERR_PTR(-EPERM);
@@ -174,10 +180,11 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
                                sg_set_page(&chunk->page_list[i], page_list[i + off], PAGE_SIZE, 0);
                        }
 
-                       chunk->nmap = ib_dma_map_sg(context->device,
-                                                   &chunk->page_list[0],
-                                                   chunk->nents,
-                                                   DMA_BIDIRECTIONAL);
+                       chunk->nmap = ib_dma_map_sg_attrs(context->device,
+                                                         &chunk->page_list[0],
+                                                         chunk->nents,
+                                                         DMA_BIDIRECTIONAL,
+                                                         &attrs);
                        if (chunk->nmap <= 0) {
                                for (i = 0; i < chunk->nents; ++i)
                                        put_page(sg_page(&chunk->page_list[i]));
index 6af2c0f79a677ab889685e4b54d6ed53c580850d..2acf9b62cf9936acf72f25f2c15bc8bdee41493d 100644 (file)
@@ -452,7 +452,7 @@ static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
                return ERR_PTR(-ENOMEM);
        c2mr->pd = c2pd;
 
-       c2mr->umem = ib_umem_get(pd->uobject->context, start, length, acc);
+       c2mr->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0);
        if (IS_ERR(c2mr->umem)) {
                err = PTR_ERR(c2mr->umem);
                kfree(c2mr);
index 66eb7030aea83c1d01f89838621959d28cf191b6..ed2ee4ba4b7c3e9e50ed8d162fbc40b5482945ca 100644 (file)
@@ -456,7 +456,8 @@ void cxio_count_scqes(struct t3_cq *cq, struct t3_wq *wq, int *count)
        ptr = cq->sw_rptr;
        while (!Q_EMPTY(ptr, cq->sw_wptr)) {
                cqe = cq->sw_queue + (Q_PTR2IDX(ptr, cq->size_log2));
-               if ((SQ_TYPE(*cqe) || (CQE_OPCODE(*cqe) == T3_READ_RESP)) &&
+               if ((SQ_TYPE(*cqe) ||
+                    ((CQE_OPCODE(*cqe) == T3_READ_RESP) && wq->oldest_read)) &&
                    (CQE_QPID(*cqe) == wq->qpid))
                        (*count)++;
                ptr++;
@@ -829,7 +830,8 @@ int cxio_rdma_init(struct cxio_rdev *rdev_p, struct t3_rdma_init_attr *attr)
        wqe->mpaattrs = attr->mpaattrs;
        wqe->qpcaps = attr->qpcaps;
        wqe->ulpdu_size = cpu_to_be16(attr->tcp_emss);
-       wqe->flags = cpu_to_be32(attr->flags);
+       wqe->rqe_count = cpu_to_be16(attr->rqe_count);
+       wqe->flags_rtr_type = cpu_to_be16(attr->flags|V_RTR_TYPE(attr->rtr_type));
        wqe->ord = cpu_to_be32(attr->ord);
        wqe->ird = cpu_to_be32(attr->ird);
        wqe->qp_dma_addr = cpu_to_be64(attr->qp_dma_addr);
@@ -1134,6 +1136,18 @@ int cxio_poll_cq(struct t3_wq *wq, struct t3_cq *cq, struct t3_cqe *cqe,
         */
        if (RQ_TYPE(*hw_cqe) && (CQE_OPCODE(*hw_cqe) == T3_READ_RESP)) {
 
+               /*
+                * If this is an unsolicited read response, then the read
+                * was generated by the kernel driver as part of peer-2-peer
+                * connection setup.  So ignore the completion.
+                */
+               if (!wq->oldest_read) {
+                       if (CQE_STATUS(*hw_cqe))
+                               wq->error = 1;
+                       ret = -1;
+                       goto skip_cqe;
+               }
+
                /*
                 * Don't write to the HWCQ, so create a new read req CQE
                 * in local memory.
index 99543d634704d93c98b1f4bcfa615a5aee7bfc0d..2bcff7f5046e3a00c10675643f40872319bb51ef 100644 (file)
@@ -53,6 +53,7 @@
 #define T3_MAX_PBL_SIZE 256
 #define T3_MAX_RQ_SIZE 1024
 #define T3_MAX_NUM_STAG (1<<15)
+#define T3_MAX_MR_SIZE 0x100000000ULL
 
 #define T3_STAG_UNSET 0xffffffff
 
index 969d4d928455b237ac97deda8f7a1e1cf38b63df..f1a25a821a45049f6c5688b92ca4d5c14b6e9fcf 100644 (file)
@@ -278,6 +278,17 @@ enum t3_qp_caps {
        uP_RI_QP_STAG0_ENABLE = 0x10
 } __attribute__ ((packed));
 
+enum rdma_init_rtr_types {
+       RTR_READ = 1,
+       RTR_WRITE = 2,
+       RTR_SEND = 3,
+};
+
+#define S_RTR_TYPE     2
+#define M_RTR_TYPE     0x3
+#define V_RTR_TYPE(x)  ((x) << S_RTR_TYPE)
+#define G_RTR_TYPE(x)  ((((x) >> S_RTR_TYPE)) & M_RTR_TYPE)
+
 struct t3_rdma_init_attr {
        u32 tid;
        u32 qpid;
@@ -293,7 +304,9 @@ struct t3_rdma_init_attr {
        u32 ird;
        u64 qp_dma_addr;
        u32 qp_dma_size;
-       u32 flags;
+       enum rdma_init_rtr_types rtr_type;
+       u16 flags;
+       u16 rqe_count;
        u32 irs;
 };
 
@@ -309,8 +322,8 @@ struct t3_rdma_init_wr {
        u8 mpaattrs;            /* 5 */
        u8 qpcaps;
        __be16 ulpdu_size;
-       __be32 flags;           /* bits 31-1 - reservered */
-                               /* bit     0 - set if RECV posted */
+       __be16 flags_rtr_type;
+       __be16 rqe_count;
        __be32 ord;             /* 6 */
        __be32 ird;
        __be64 qp_dma_addr;     /* 7 */
@@ -324,7 +337,7 @@ struct t3_genbit {
 };
 
 enum rdma_init_wr_flags {
-       RECVS_POSTED = (1<<0),
+       MPA_INITIATOR = (1<<0),
        PRIV_QP = (1<<1),
 };
 
index 6ba4138c8ec3a8b434526e7f7ceba7f641569d62..71554eacb13ce3f87d19b8bd582f05eabde6a8f9 100644 (file)
@@ -83,6 +83,7 @@ static void rnic_init(struct iwch_dev *rnicp)
        rnicp->attr.max_phys_buf_entries = T3_MAX_PBL_SIZE;
        rnicp->attr.max_pds = T3_MAX_NUM_PD - 1;
        rnicp->attr.mem_pgsizes_bitmask = 0x7FFF;       /* 4KB-128MB */
+       rnicp->attr.max_mr_size = T3_MAX_MR_SIZE;
        rnicp->attr.can_resize_wq = 0;
        rnicp->attr.max_rdma_reads_per_qp = 8;
        rnicp->attr.max_rdma_read_resources =
index 9ad9b1e7c8c1cced39eda9ead95d85e498018a03..d2409a505e8d5d3f6b659b4af0a07d0421cf8672 100644 (file)
@@ -66,6 +66,7 @@ struct iwch_rnic_attributes {
         * size (4k)^i.  Phys block list mode unsupported.
         */
        u32 mem_pgsizes_bitmask;
+       u64 max_mr_size;
        u8 can_resize_wq;
 
        /*
index 72ca360c3dbc12c2b0a36e865b5ad18601eb3bd2..d44a6df9ad8c4a7ebd915b00817a8a980ae2f237 100644 (file)
@@ -63,6 +63,10 @@ static char *states[] = {
        NULL,
 };
 
+int peer2peer = 0;
+module_param(peer2peer, int, 0644);
+MODULE_PARM_DESC(peer2peer, "Support peer2peer ULPs (default=0)");
+
 static int ep_timeout_secs = 10;
 module_param(ep_timeout_secs, int, 0644);
 MODULE_PARM_DESC(ep_timeout_secs, "CM Endpoint operation timeout "
@@ -125,6 +129,12 @@ static void start_ep_timer(struct iwch_ep *ep)
 static void stop_ep_timer(struct iwch_ep *ep)
 {
        PDBG("%s ep %p\n", __func__, ep);
+       if (!timer_pending(&ep->timer)) {
+               printk(KERN_ERR "%s timer stopped when its not running!  ep %p state %u\n",
+                       __func__, ep, ep->com.state);
+               WARN_ON(1);
+               return;
+       }
        del_timer_sync(&ep->timer);
        put_ep(&ep->com);
 }
@@ -508,7 +518,7 @@ static void send_mpa_req(struct iwch_ep *ep, struct sk_buff *skb)
        skb_reset_transport_header(skb);
        len = skb->len;
        req = (struct tx_data_wr *) skb_push(skb, sizeof(*req));
-       req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA));
+       req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA)|F_WR_COMPL);
        req->wr_lo = htonl(V_WR_TID(ep->hwtid));
        req->len = htonl(len);
        req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
@@ -559,7 +569,7 @@ static int send_mpa_reject(struct iwch_ep *ep, const void *pdata, u8 plen)
        set_arp_failure_handler(skb, arp_failure_discard);
        skb_reset_transport_header(skb);
        req = (struct tx_data_wr *) skb_push(skb, sizeof(*req));
-       req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA));
+       req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA)|F_WR_COMPL);
        req->wr_lo = htonl(V_WR_TID(ep->hwtid));
        req->len = htonl(mpalen);
        req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
@@ -611,7 +621,7 @@ static int send_mpa_reply(struct iwch_ep *ep, const void *pdata, u8 plen)
        skb_reset_transport_header(skb);
        len = skb->len;
        req = (struct tx_data_wr *) skb_push(skb, sizeof(*req));
-       req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA));
+       req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA)|F_WR_COMPL);
        req->wr_lo = htonl(V_WR_TID(ep->hwtid));
        req->len = htonl(len);
        req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
@@ -879,6 +889,7 @@ static void process_mpa_reply(struct iwch_ep *ep, struct sk_buff *skb)
         * the MPA header is valid.
         */
        state_set(&ep->com, FPDU_MODE);
+       ep->mpa_attr.initiator = 1;
        ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
        ep->mpa_attr.recv_marker_enabled = markers_enabled;
        ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
@@ -901,8 +912,14 @@ static void process_mpa_reply(struct iwch_ep *ep, struct sk_buff *skb)
        /* bind QP and TID with INIT_WR */
        err = iwch_modify_qp(ep->com.qp->rhp,
                             ep->com.qp, mask, &attrs, 1);
-       if (!err)
-               goto out;
+       if (err)
+               goto err;
+
+       if (peer2peer && iwch_rqes_posted(ep->com.qp) == 0) {
+               iwch_post_zb_read(ep->com.qp);
+       }
+
+       goto out;
 err:
        abort_connection(ep, skb, GFP_KERNEL);
 out:
@@ -995,6 +1012,7 @@ static void process_mpa_request(struct iwch_ep *ep, struct sk_buff *skb)
         * If we get here we have accumulated the entire mpa
         * start reply message including private data.
         */
+       ep->mpa_attr.initiator = 0;
        ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
        ep->mpa_attr.recv_marker_enabled = markers_enabled;
        ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
@@ -1065,17 +1083,33 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
 
        PDBG("%s ep %p credits %u\n", __func__, ep, credits);
 
-       if (credits == 0)
+       if (credits == 0) {
+               PDBG(KERN_ERR "%s 0 credit ack  ep %p state %u\n",
+                       __func__, ep, state_read(&ep->com));
                return CPL_RET_BUF_DONE;
+       }
+
        BUG_ON(credits != 1);
-       BUG_ON(ep->mpa_skb == NULL);
-       kfree_skb(ep->mpa_skb);
-       ep->mpa_skb = NULL;
        dst_confirm(ep->dst);
-       if (state_read(&ep->com) == MPA_REP_SENT) {
-               ep->com.rpl_done = 1;
-               PDBG("waking up ep %p\n", ep);
-               wake_up(&ep->com.waitq);
+       if (!ep->mpa_skb) {
+               PDBG("%s rdma_init wr_ack ep %p state %u\n",
+                       __func__, ep, state_read(&ep->com));
+               if (ep->mpa_attr.initiator) {
+                       PDBG("%s initiator ep %p state %u\n",
+                               __func__, ep, state_read(&ep->com));
+                       if (peer2peer)
+                               iwch_post_zb_read(ep->com.qp);
+               } else {
+                       PDBG("%s responder ep %p state %u\n",
+                               __func__, ep, state_read(&ep->com));
+                       ep->com.rpl_done = 1;
+                       wake_up(&ep->com.waitq);
+               }
+       } else {
+               PDBG("%s lsm ack ep %p state %u freeing skb\n",
+                       __func__, ep, state_read(&ep->com));
+               kfree_skb(ep->mpa_skb);
+               ep->mpa_skb = NULL;
        }
        return CPL_RET_BUF_DONE;
 }
@@ -1083,8 +1117,11 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
 static int abort_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
 {
        struct iwch_ep *ep = ctx;
+       unsigned long flags;
+       int release = 0;
 
        PDBG("%s ep %p\n", __func__, ep);
+       BUG_ON(!ep);
 
        /*
         * We get 2 abort replies from the HW.  The first one must
@@ -1095,9 +1132,22 @@ static int abort_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
                return CPL_RET_BUF_DONE;
        }
 
-       close_complete_upcall(ep);
-       state_set(&ep->com, DEAD);
-       release_ep_resources(ep);
+       spin_lock_irqsave(&ep->com.lock, flags);
+       switch (ep->com.state) {
+       case ABORTING:
+               close_complete_upcall(ep);
+               __state_set(&ep->com, DEAD);
+               release = 1;
+               break;
+       default:
+               printk(KERN_ERR "%s ep %p state %d\n",
+                    __func__, ep, ep->com.state);
+               break;
+       }
+       spin_unlock_irqrestore(&ep->com.lock, flags);
+
+       if (release)
+               release_ep_resources(ep);
        return CPL_RET_BUF_DONE;
 }
 
@@ -1470,7 +1520,8 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
        struct sk_buff *rpl_skb;
        struct iwch_qp_attributes attrs;
        int ret;
-       int state;
+       int release = 0;
+       unsigned long flags;
 
        if (is_neg_adv_abort(req->status)) {
                PDBG("%s neg_adv_abort ep %p tid %d\n", __func__, ep,
@@ -1488,9 +1539,9 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
                return CPL_RET_BUF_DONE;
        }
 
-       state = state_read(&ep->com);
-       PDBG("%s ep %p state %u\n", __func__, ep, state);
-       switch (state) {
+       spin_lock_irqsave(&ep->com.lock, flags);
+       PDBG("%s ep %p state %u\n", __func__, ep, ep->com.state);
+       switch (ep->com.state) {
        case CONNECTING:
                break;
        case MPA_REQ_WAIT:
@@ -1536,21 +1587,25 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
                break;
        case DEAD:
                PDBG("%s PEER_ABORT IN DEAD STATE!!!!\n", __func__);
+               spin_unlock_irqrestore(&ep->com.lock, flags);
                return CPL_RET_BUF_DONE;
        default:
                BUG_ON(1);
                break;
        }
        dst_confirm(ep->dst);
+       if (ep->com.state != ABORTING) {
+               __state_set(&ep->com, DEAD);
+               release = 1;
+       }
+       spin_unlock_irqrestore(&ep->com.lock, flags);
 
        rpl_skb = get_skb(skb, sizeof(*rpl), GFP_KERNEL);
        if (!rpl_skb) {
                printk(KERN_ERR MOD "%s - cannot allocate skb!\n",
                       __func__);
-               dst_release(ep->dst);
-               l2t_release(L2DATA(ep->com.tdev), ep->l2t);
-               put_ep(&ep->com);
-               return CPL_RET_BUF_DONE;
+               release = 1;
+               goto out;
        }
        rpl_skb->priority = CPL_PRIORITY_DATA;
        rpl = (struct cpl_abort_rpl *) skb_put(rpl_skb, sizeof(*rpl));
@@ -1559,10 +1614,9 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
        OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_ABORT_RPL, ep->hwtid));
        rpl->cmd = CPL_ABORT_NO_RST;
        cxgb3_ofld_send(ep->com.tdev, rpl_skb);
-       if (state != ABORTING) {
-               state_set(&ep->com, DEAD);
+out:
+       if (release)
                release_ep_resources(ep);
-       }
        return CPL_RET_BUF_DONE;
 }
 
@@ -1661,15 +1715,18 @@ static void ep_timeout(unsigned long arg)
        struct iwch_ep *ep = (struct iwch_ep *)arg;
        struct iwch_qp_attributes attrs;
        unsigned long flags;
+       int abort = 1;
 
        spin_lock_irqsave(&ep->com.lock, flags);
        PDBG("%s ep %p tid %u state %d\n", __func__, ep, ep->hwtid,
             ep->com.state);
        switch (ep->com.state) {
        case MPA_REQ_SENT:
+               __state_set(&ep->com, ABORTING);
                connect_reply_upcall(ep, -ETIMEDOUT);
                break;
        case MPA_REQ_WAIT:
+               __state_set(&ep->com, ABORTING);
                break;
        case CLOSING:
        case MORIBUND:
@@ -1679,13 +1736,17 @@ static void ep_timeout(unsigned long arg)
                                     ep->com.qp, IWCH_QP_ATTR_NEXT_STATE,
                                     &attrs, 1);
                }
+               __state_set(&ep->com, ABORTING);
                break;
        default:
-               BUG();
+               printk(KERN_ERR "%s unexpected state ep %p state %u\n",
+                       __func__, ep, ep->com.state);
+               WARN_ON(1);
+               abort = 0;
        }
-       __state_set(&ep->com, CLOSING);
        spin_unlock_irqrestore(&ep->com.lock, flags);
-       abort_connection(ep, NULL, GFP_ATOMIC);
+       if (abort)
+               abort_connection(ep, NULL, GFP_ATOMIC);
        put_ep(&ep->com);
 }
 
@@ -1762,16 +1823,19 @@ int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        if (err)
                goto err;
 
+       /* if needed, wait for wr_ack */
+       if (iwch_rqes_posted(qp)) {
+               wait_event(ep->com.waitq, ep->com.rpl_done);
+               err = ep->com.rpl_err;
+               if (err)
+                       goto err;
+       }
+
        err = send_mpa_reply(ep, conn_param->private_data,
                             conn_param->private_data_len);
        if (err)
                goto err;
 
-       /* wait for wr_ack */
-       wait_event(ep->com.waitq, ep->com.rpl_done);
-       err = ep->com.rpl_err;
-       if (err)
-               goto err;
 
        state_set(&ep->com, FPDU_MODE);
        established_upcall(ep);
@@ -1968,40 +2032,39 @@ int iwch_ep_disconnect(struct iwch_ep *ep, int abrupt, gfp_t gfp)
        PDBG("%s ep %p state %s, abrupt %d\n", __func__, ep,
             states[ep->com.state], abrupt);
 
-       if (ep->com.state == DEAD) {
-               PDBG("%s already dead ep %p\n", __func__, ep);
-               goto out;
-       }
-
-       if (abrupt) {
-               if (ep->com.state != ABORTING) {
-                       ep->com.state = ABORTING;
-                       close = 1;
-               }
-               goto out;
-       }
-
        switch (ep->com.state) {
        case MPA_REQ_WAIT:
        case MPA_REQ_SENT:
        case MPA_REQ_RCVD:
        case MPA_REP_SENT:
        case FPDU_MODE:
-               start_ep_timer(ep);
-               ep->com.state = CLOSING;
                close = 1;
+               if (abrupt)
+                       ep->com.state = ABORTING;
+               else {
+                       ep->com.state = CLOSING;
+                       start_ep_timer(ep);
+               }
                break;
        case CLOSING:
-               ep->com.state = MORIBUND;
                close = 1;
+               if (abrupt) {
+                       stop_ep_timer(ep);
+                       ep->com.state = ABORTING;
+               } else
+                       ep->com.state = MORIBUND;
                break;
        case MORIBUND:
+       case ABORTING:
+       case DEAD:
+               PDBG("%s ignoring disconnect ep %p state %u\n",
+                    __func__, ep, ep->com.state);
                break;
        default:
                BUG();
                break;
        }
-out:
+
        spin_unlock_irqrestore(&ep->com.lock, flags);
        if (close) {
                if (abrupt)
index 2bb7fbdb3ff44e3136a7e2c0d7edcec9b97e842f..d7c7e09f09963c29fcd593175c92db5cfba582a0 100644 (file)
@@ -56,6 +56,7 @@
 #define put_ep(ep) { \
        PDBG("put_ep (via %s:%u) ep %p refcnt %d\n", __func__, __LINE__,  \
             ep, atomic_read(&((ep)->kref.refcount))); \
+       WARN_ON(atomic_read(&((ep)->kref.refcount)) < 1); \
        kref_put(&((ep)->kref), __free_ep); \
 }
 
@@ -225,5 +226,6 @@ int iwch_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new, st
 
 int __init iwch_cm_init(void);
 void __exit iwch_cm_term(void);
+extern int peer2peer;
 
 #endif                         /* _IWCH_CM_H_ */
index ab4695c1dd5614b3e881ad6d03abca913621ebf6..d07d3a377b5f2b02644e2164db56b858ac898e07 100644 (file)
@@ -602,7 +602,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
        if (!mhp)
                return ERR_PTR(-ENOMEM);
 
-       mhp->umem = ib_umem_get(pd->uobject->context, start, length, acc);
+       mhp->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0);
        if (IS_ERR(mhp->umem)) {
                err = PTR_ERR(mhp->umem);
                kfree(mhp);
@@ -998,7 +998,7 @@ static int iwch_query_device(struct ib_device *ibdev,
        props->device_cap_flags = dev->device_cap_flags;
        props->vendor_id = (u32)dev->rdev.rnic_info.pdev->vendor;
        props->vendor_part_id = (u32)dev->rdev.rnic_info.pdev->device;
-       props->max_mr_size = ~0ull;
+       props->max_mr_size = dev->attr.max_mr_size;
        props->max_qp = dev->attr.max_qps;
        props->max_qp_wr = dev->attr.max_wrs;
        props->max_sge = dev->attr.max_sge_per_wr;
index 61356f91109d8fd96e611cc55bb40a1b64f20997..db5100d27ca2e9f7746cb26444488c80883be292 100644 (file)
@@ -118,6 +118,7 @@ enum IWCH_QP_FLAGS {
 };
 
 struct iwch_mpa_attributes {
+       u8 initiator;
        u8 recv_marker_enabled;
        u8 xmit_marker_enabled; /* iWARP: enable inbound Read Resp. */
        u8 crc_enabled;
@@ -322,6 +323,7 @@ enum iwch_qp_query_flags {
        IWCH_QP_QUERY_TEST_USERWRITE = 0x32     /* Test special */
 };
 
+u16 iwch_rqes_posted(struct iwch_qp *qhp);
 int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                      struct ib_send_wr **bad_wr);
 int iwch_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
@@ -331,6 +333,7 @@ int iwch_bind_mw(struct ib_qp *qp,
                             struct ib_mw_bind *mw_bind);
 int iwch_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc);
 int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg);
+int iwch_post_zb_read(struct iwch_qp *qhp);
 int iwch_register_device(struct iwch_dev *dev);
 void iwch_unregister_device(struct iwch_dev *dev);
 int iwch_quiesce_qps(struct iwch_cq *chp);
index 8891c3b0a3d51d1ecc1e2e47766a27d91a4c8be6..9b4be889c58ea8d9d378200e0297958a337ef16c 100644 (file)
@@ -586,6 +586,36 @@ static inline void build_term_codes(struct respQ_msg_t *rsp_msg,
        }
 }
 
+int iwch_post_zb_read(struct iwch_qp *qhp)
+{
+       union t3_wr *wqe;
+       struct sk_buff *skb;
+       u8 flit_cnt = sizeof(struct t3_rdma_read_wr) >> 3;
+
+       PDBG("%s enter\n", __func__);
+       skb = alloc_skb(40, GFP_KERNEL);
+       if (!skb) {
+               printk(KERN_ERR "%s cannot send zb_read!!\n", __func__);
+               return -ENOMEM;
+       }
+       wqe = (union t3_wr *)skb_put(skb, sizeof(struct t3_rdma_read_wr));
+       memset(wqe, 0, sizeof(struct t3_rdma_read_wr));
+       wqe->read.rdmaop = T3_READ_REQ;
+       wqe->read.reserved[0] = 0;
+       wqe->read.reserved[1] = 0;
+       wqe->read.reserved[2] = 0;
+       wqe->read.rem_stag = cpu_to_be32(1);
+       wqe->read.rem_to = cpu_to_be64(1);
+       wqe->read.local_stag = cpu_to_be32(1);
+       wqe->read.local_len = cpu_to_be32(0);
+       wqe->read.local_to = cpu_to_be64(1);
+       wqe->send.wrh.op_seop_flags = cpu_to_be32(V_FW_RIWR_OP(T3_WR_READ));
+       wqe->send.wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(qhp->ep->hwtid)|
+                                               V_FW_RIWR_LEN(flit_cnt));
+       skb->priority = CPL_PRIORITY_DATA;
+       return cxgb3_ofld_send(qhp->rhp->rdev.t3cdev_p, skb);
+}
+
 /*
  * This posts a TERMINATE with layer=RDMA, type=catastrophic.
  */
@@ -671,11 +701,18 @@ static void flush_qp(struct iwch_qp *qhp, unsigned long *flag)
 
 
 /*
- * Return non zero if at least one RECV was pre-posted.
+ * Return count of RECV WRs posted
  */
-static int rqes_posted(struct iwch_qp *qhp)
+u16 iwch_rqes_posted(struct iwch_qp *qhp)
 {
-       return fw_riwrh_opcode((struct fw_riwrh *)qhp->wq.queue) == T3_WR_RCV;
+       union t3_wr *wqe = qhp->wq.queue;
+       u16 count = 0;
+       while ((count+1) != 0 && fw_riwrh_opcode((struct fw_riwrh *)wqe) == T3_WR_RCV) {
+               count++;
+               wqe++;
+       }
+       PDBG("%s qhp %p count %u\n", __func__, qhp, count);
+       return count;
 }
 
 static int rdma_init(struct iwch_dev *rhp, struct iwch_qp *qhp,
@@ -716,8 +753,17 @@ static int rdma_init(struct iwch_dev *rhp, struct iwch_qp *qhp,
        init_attr.ird = qhp->attr.max_ird;
        init_attr.qp_dma_addr = qhp->wq.dma_addr;
        init_attr.qp_dma_size = (1UL << qhp->wq.size_log2);
-       init_attr.flags = rqes_posted(qhp) ? RECVS_POSTED : 0;
+       init_attr.rqe_count = iwch_rqes_posted(qhp);
+       init_attr.flags = qhp->attr.mpa_attr.initiator ? MPA_INITIATOR : 0;
        init_attr.flags |= capable(CAP_NET_BIND_SERVICE) ? PRIV_QP : 0;
+       if (peer2peer) {
+               init_attr.rtr_type = RTR_READ;
+               if (init_attr.ord == 0 && qhp->attr.mpa_attr.initiator)
+                       init_attr.ord = 1;
+               if (init_attr.ird == 0 && !qhp->attr.mpa_attr.initiator)
+                       init_attr.ird = 1;
+       } else
+               init_attr.rtr_type = 0;
        init_attr.irs = qhp->ep->rcv_seq;
        PDBG("%s init_attr.rq_addr 0x%x init_attr.rq_size = %d "
             "flags 0x%x qpcaps 0x%x\n", __func__,
@@ -832,6 +878,7 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
                                abort=0;
                                disconnect = 1;
                                ep = qhp->ep;
+                               get_ep(&ep->com);
                        }
                        flush_qp(qhp, &flag);
                        break;
@@ -848,6 +895,7 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
                                abort=1;
                                disconnect = 1;
                                ep = qhp->ep;
+                               get_ep(&ep->com);
                        }
                        goto err;
                        break;
@@ -929,8 +977,10 @@ out:
         * on the EP.  This can be a normal close (RTS->CLOSING) or
         * an abnormal close (RTS/CLOSING->ERROR).
         */
-       if (disconnect)
+       if (disconnect) {
                iwch_ep_disconnect(ep, abort, GFP_KERNEL);
+               put_ep(&ep->com);
+       }
 
        /*
         * If free is 1, then we've disassociated the EP from the QP
index 3d6d9461c31da089eb2aee091a9286e4d994e6e9..00bab60f6de474a1ed24e77ee9331f46efe7103f 100644 (file)
@@ -66,6 +66,7 @@ struct ehca_av;
 #include "ehca_irq.h"
 
 #define EHCA_EQE_CACHE_SIZE 20
+#define EHCA_MAX_NUM_QUEUES 0xffff
 
 struct ehca_eqe_cache_entry {
        struct ehca_eqe *eqe;
@@ -127,6 +128,8 @@ struct ehca_shca {
        /* MR pgsize: bit 0-3 means 4K, 64K, 1M, 16M respectively */
        u32 hca_cap_mr_pgsize;
        int max_mtu;
+       atomic_t num_cqs;
+       atomic_t num_qps;
 };
 
 struct ehca_pd {
@@ -344,6 +347,8 @@ extern int ehca_use_hp_mr;
 extern int ehca_scaling_code;
 extern int ehca_lock_hcalls;
 extern int ehca_nr_ports;
+extern int ehca_max_cq;
+extern int ehca_max_qp;
 
 struct ipzu_queue_resp {
        u32 qe_size;      /* queue entry size */
index ec0cfcf3073f305dfd6ac796016f273f4db6f58f..5540b276a33cab4877bdf56833f16fc0c316fb22 100644 (file)
@@ -132,10 +132,19 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
        if (cqe >= 0xFFFFFFFF - 64 - additional_cqe)
                return ERR_PTR(-EINVAL);
 
+       if (!atomic_add_unless(&shca->num_cqs, 1, ehca_max_cq)) {
+               ehca_err(device, "Unable to create CQ, max number of %i "
+                       "CQs reached.", ehca_max_cq);
+               ehca_err(device, "To increase the maximum number of CQs "
+                       "use the number_of_cqs module parameter.\n");
+               return ERR_PTR(-ENOSPC);
+       }
+
        my_cq = kmem_cache_zalloc(cq_cache, GFP_KERNEL);
        if (!my_cq) {
                ehca_err(device, "Out of memory for ehca_cq struct device=%p",
                         device);
+               atomic_dec(&shca->num_cqs);
                return ERR_PTR(-ENOMEM);
        }
 
@@ -305,6 +314,7 @@ create_cq_exit2:
 create_cq_exit1:
        kmem_cache_free(cq_cache, my_cq);
 
+       atomic_dec(&shca->num_cqs);
        return cq;
 }
 
@@ -359,6 +369,7 @@ int ehca_destroy_cq(struct ib_cq *cq)
        ipz_queue_dtor(NULL, &my_cq->ipz_queue);
        kmem_cache_free(cq_cache, my_cq);
 
+       atomic_dec(&shca->num_cqs);
        return 0;
 }
 
index b4ac617a70e65e3f8200bd6381156eff2408b73b..49660dfa186785f8d73b16b84e0ddcc141967cac 100644 (file)
@@ -54,7 +54,8 @@ int ehca_create_eq(struct ehca_shca *shca,
                   struct ehca_eq *eq,
                   const enum ehca_eq_type type, const u32 length)
 {
-       u64 ret;
+       int ret;
+       u64 h_ret;
        u32 nr_pages;
        u32 i;
        void *vpage;
@@ -73,15 +74,15 @@ int ehca_create_eq(struct ehca_shca *shca,
                return -EINVAL;
        }
 
-       ret = hipz_h_alloc_resource_eq(shca->ipz_hca_handle,
-                                      &eq->pf,
-                                      type,
-                                      length,
-                                      &eq->ipz_eq_handle,
-                                      &eq->length,
-                                      &nr_pages, &eq->ist);
+       h_ret = hipz_h_alloc_resource_eq(shca->ipz_hca_handle,
+                                        &eq->pf,
+                                        type,
+                                        length,
+                                        &eq->ipz_eq_handle,
+                                        &eq->length,
+                                        &nr_pages, &eq->ist);
 
-       if (ret != H_SUCCESS) {
+       if (h_ret != H_SUCCESS) {
                ehca_err(ib_dev, "Can't allocate EQ/NEQ. eq=%p", eq);
                return -EINVAL;
        }
@@ -97,24 +98,22 @@ int ehca_create_eq(struct ehca_shca *shca,
                u64 rpage;
 
                vpage = ipz_qpageit_get_inc(&eq->ipz_queue);
-               if (!vpage) {
-                       ret = H_RESOURCE;
+               if (!vpage)
                        goto create_eq_exit2;
-               }
 
                rpage = virt_to_abs(vpage);
-               ret = hipz_h_register_rpage_eq(shca->ipz_hca_handle,
-                                              eq->ipz_eq_handle,
-                                              &eq->pf,
-                                              0, 0, rpage, 1);
+               h_ret = hipz_h_register_rpage_eq(shca->ipz_hca_handle,
+                                                eq->ipz_eq_handle,
+                                                &eq->pf,
+                                                0, 0, rpage, 1);
 
                if (i == (nr_pages - 1)) {
                        /* last page */
                        vpage = ipz_qpageit_get_inc(&eq->ipz_queue);
-                       if (ret != H_SUCCESS || vpage)
+                       if (h_ret != H_SUCCESS || vpage)
                                goto create_eq_exit2;
                } else {
-                       if (ret != H_PAGE_REGISTERED || !vpage)
+                       if (h_ret != H_PAGE_REGISTERED || !vpage)
                                goto create_eq_exit2;
                }
        }
index 65048976198c5ed63863de8b21b04f576783f744..482103eb6eacdc699430c7455e9e9b723515443f 100644 (file)
@@ -68,6 +68,8 @@ int ehca_port_act_time = 30;
 int ehca_static_rate   = -1;
 int ehca_scaling_code  = 0;
 int ehca_lock_hcalls   = -1;
+int ehca_max_cq        = -1;
+int ehca_max_qp        = -1;
 
 module_param_named(open_aqp1,     ehca_open_aqp1,     bool, S_IRUGO);
 module_param_named(debug_level,   ehca_debug_level,   int,  S_IRUGO);
@@ -79,6 +81,8 @@ module_param_named(poll_all_eqs,  ehca_poll_all_eqs,  bool, S_IRUGO);
 module_param_named(static_rate,   ehca_static_rate,   int,  S_IRUGO);
 module_param_named(scaling_code,  ehca_scaling_code,  bool, S_IRUGO);
 module_param_named(lock_hcalls,   ehca_lock_hcalls,   bool, S_IRUGO);
+module_param_named(number_of_cqs, ehca_max_cq,        int,  S_IRUGO);
+module_param_named(number_of_qps, ehca_max_qp,        int,  S_IRUGO);
 
 MODULE_PARM_DESC(open_aqp1,
                 "Open AQP1 on startup (default: no)");
@@ -104,6 +108,12 @@ MODULE_PARM_DESC(scaling_code,
 MODULE_PARM_DESC(lock_hcalls,
                 "Serialize all hCalls made by the driver "
                 "(default: autodetect)");
+MODULE_PARM_DESC(number_of_cqs,
+               "Max number of CQs which can be allocated "
+               "(default: autodetect)");
+MODULE_PARM_DESC(number_of_qps,
+               "Max number of QPs which can be allocated "
+               "(default: autodetect)");
 
 DEFINE_RWLOCK(ehca_qp_idr_lock);
 DEFINE_RWLOCK(ehca_cq_idr_lock);
@@ -355,6 +365,25 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
                if (rblock->memory_page_size_supported & pgsize_map[i])
                        shca->hca_cap_mr_pgsize |= pgsize_map[i + 1];
 
+       /* Set maximum number of CQs and QPs to calculate EQ size */
+       if (ehca_max_qp == -1)
+               ehca_max_qp = min_t(int, rblock->max_qp, EHCA_MAX_NUM_QUEUES);
+       else if (ehca_max_qp < 1 || ehca_max_qp > rblock->max_qp) {
+               ehca_gen_err("Requested number of QPs is out of range (1 - %i) "
+                       "specified by HW", rblock->max_qp);
+               ret = -EINVAL;
+               goto sense_attributes1;
+       }
+
+       if (ehca_max_cq == -1)
+               ehca_max_cq = min_t(int, rblock->max_cq, EHCA_MAX_NUM_QUEUES);
+       else if (ehca_max_cq < 1 || ehca_max_cq > rblock->max_cq) {
+               ehca_gen_err("Requested number of CQs is out of range (1 - %i) "
+                       "specified by HW", rblock->max_cq);
+               ret = -EINVAL;
+               goto sense_attributes1;
+       }
+
        /* query max MTU from first port -- it's the same for all ports */
        port = (struct hipz_query_port *)rblock;
        h_ret = hipz_h_query_port(shca->ipz_hca_handle, 1, port);
@@ -684,7 +713,7 @@ static int __devinit ehca_probe(struct of_device *dev,
        struct ehca_shca *shca;
        const u64 *handle;
        struct ib_pd *ibpd;
-       int ret, i;
+       int ret, i, eq_size;
 
        handle = of_get_property(dev->node, "ibm,hca-handle", NULL);
        if (!handle) {
@@ -705,6 +734,8 @@ static int __devinit ehca_probe(struct of_device *dev,
                return -ENOMEM;
        }
        mutex_init(&shca->modify_mutex);
+       atomic_set(&shca->num_cqs, 0);
+       atomic_set(&shca->num_qps, 0);
        for (i = 0; i < ARRAY_SIZE(shca->sport); i++)
                spin_lock_init(&shca->sport[i].mod_sqp_lock);
 
@@ -724,8 +755,9 @@ static int __devinit ehca_probe(struct of_device *dev,
                goto probe1;
        }
 
+       eq_size = 2 * ehca_max_cq + 4 * ehca_max_qp;
        /* create event queues */
-       ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, 2048);
+       ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, eq_size);
        if (ret) {
                ehca_err(&shca->ib_device, "Cannot create EQ.");
                goto probe1;
index 46ae4eb2c4e1e096a4bce1bbef180474d64ec335..f974367cad4007475a314237768c358d50a236ac 100644 (file)
@@ -323,7 +323,7 @@ struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
        }
 
        e_mr->umem = ib_umem_get(pd->uobject->context, start, length,
-                                mr_access_flags);
+                                mr_access_flags, 0);
        if (IS_ERR(e_mr->umem)) {
                ib_mr = (void *)e_mr->umem;
                goto reg_user_mr_exit1;
index 57bef1152cc2d3bc7459836c61a4b8a24baed2de..18fba92fa7ae107311121b7cc591aa077c7b51eb 100644 (file)
@@ -421,8 +421,18 @@ static struct ehca_qp *internal_create_qp(
        u32 swqe_size = 0, rwqe_size = 0, ib_qp_num;
        unsigned long flags;
 
-       if (init_attr->create_flags)
+       if (!atomic_add_unless(&shca->num_qps, 1, ehca_max_qp)) {
+               ehca_err(pd->device, "Unable to create QP, max number of %i "
+                        "QPs reached.", ehca_max_qp);
+               ehca_err(pd->device, "To increase the maximum number of QPs "
+                        "use the number_of_qps module parameter.\n");
+               return ERR_PTR(-ENOSPC);
+       }
+
+       if (init_attr->create_flags) {
+               atomic_dec(&shca->num_qps);
                return ERR_PTR(-EINVAL);
+       }
 
        memset(&parms, 0, sizeof(parms));
        qp_type = init_attr->qp_type;
@@ -431,6 +441,7 @@ static struct ehca_qp *internal_create_qp(
                init_attr->sq_sig_type != IB_SIGNAL_ALL_WR) {
                ehca_err(pd->device, "init_attr->sg_sig_type=%x not allowed",
                         init_attr->sq_sig_type);
+               atomic_dec(&shca->num_qps);
                return ERR_PTR(-EINVAL);
        }
 
@@ -455,6 +466,7 @@ static struct ehca_qp *internal_create_qp(
 
        if (is_llqp && has_srq) {
                ehca_err(pd->device, "LLQPs can't have an SRQ");
+               atomic_dec(&shca->num_qps);
                return ERR_PTR(-EINVAL);
        }
 
@@ -466,6 +478,7 @@ static struct ehca_qp *internal_create_qp(
                        ehca_err(pd->device, "no more than three SGEs "
                                 "supported for SRQ  pd=%p  max_sge=%x",
                                 pd, init_attr->cap.max_recv_sge);
+                       atomic_dec(&shca->num_qps);
                        return ERR_PTR(-EINVAL);
                }
        }
@@ -477,6 +490,7 @@ static struct ehca_qp *internal_create_qp(
            qp_type != IB_QPT_SMI &&
            qp_type != IB_QPT_GSI) {
                ehca_err(pd->device, "wrong QP Type=%x", qp_type);
+               atomic_dec(&shca->num_qps);
                return ERR_PTR(-EINVAL);
        }
 
@@ -490,6 +504,7 @@ static struct ehca_qp *internal_create_qp(
                                         "or max_rq_wr=%x for RC LLQP",
                                         init_attr->cap.max_send_wr,
                                         init_attr->cap.max_recv_wr);
+                               atomic_dec(&shca->num_qps);
                                return ERR_PTR(-EINVAL);
                        }
                        break;
@@ -497,6 +512,7 @@ static struct ehca_qp *internal_create_qp(
                        if (!EHCA_BMASK_GET(HCA_CAP_UD_LL_QP, shca->hca_cap)) {
                                ehca_err(pd->device, "UD LLQP not supported "
                                         "by this adapter");
+                               atomic_dec(&shca->num_qps);
                                return ERR_PTR(-ENOSYS);
                        }
                        if (!(init_attr->cap.max_send_sge <= 5
@@ -508,20 +524,22 @@ static struct ehca_qp *internal_create_qp(
                                         "or max_recv_sge=%x for UD LLQP",
                                         init_attr->cap.max_send_sge,
                                         init_attr->cap.max_recv_sge);
+                               atomic_dec(&shca->num_qps);
                                return ERR_PTR(-EINVAL);
                        } else if (init_attr->cap.max_send_wr > 255) {
                                ehca_err(pd->device,
                                         "Invalid Number of "
                                         "max_send_wr=%x for UD QP_TYPE=%x",
                                         init_attr->cap.max_send_wr, qp_type);
+                               atomic_dec(&shca->num_qps);
                                return ERR_PTR(-EINVAL);
                        }
                        break;
                default:
                        ehca_err(pd->device, "unsupported LL QP Type=%x",
                                 qp_type);
+                       atomic_dec(&shca->num_qps);
                        return ERR_PTR(-EINVAL);
-                       break;
                }
        } else {
                int max_sge = (qp_type == IB_QPT_UD || qp_type == IB_QPT_SMI
@@ -533,6 +551,7 @@ static struct ehca_qp *internal_create_qp(
                                 "send_sge=%x recv_sge=%x max_sge=%x",
                                 init_attr->cap.max_send_sge,
                                 init_attr->cap.max_recv_sge, max_sge);
+                       atomic_dec(&shca->num_qps);
                        return ERR_PTR(-EINVAL);
                }
        }
@@ -543,6 +562,7 @@ static struct ehca_qp *internal_create_qp(
        my_qp = kmem_cache_zalloc(qp_cache, GFP_KERNEL);
        if (!my_qp) {
                ehca_err(pd->device, "pd=%p not enough memory to alloc qp", pd);
+               atomic_dec(&shca->num_qps);
                return ERR_PTR(-ENOMEM);
        }
 
@@ -823,6 +843,7 @@ create_qp_exit1:
 
 create_qp_exit0:
        kmem_cache_free(qp_cache, my_qp);
+       atomic_dec(&shca->num_qps);
        return ERR_PTR(ret);
 }
 
@@ -1948,6 +1969,7 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
        if (HAS_SQ(my_qp))
                ipz_queue_dtor(my_pd, &my_qp->ipz_squeue);
        kmem_cache_free(qp_cache, my_qp);
+       atomic_dec(&shca->num_qps);
        return 0;
 }
 
index db4ba92f79fcd60736a8bd3d1e1752caa0ab3f5d..9d343b7c2f3b64b7729114a98773accab45baec8 100644 (file)
@@ -195,7 +195,8 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
                goto bail;
        }
 
-       umem = ib_umem_get(pd->uobject->context, start, length, mr_access_flags);
+       umem = ib_umem_get(pd->uobject->context, start, length,
+                          mr_access_flags, 0);
        if (IS_ERR(umem))
                return (void *) umem;
 
index 5e570bb0bb6f57fe6912bce4485b8cde60d90658..2f199c5c4a724320a8e517a5a37046d7d740923d 100644 (file)
@@ -137,7 +137,7 @@ static int mlx4_ib_get_cq_umem(struct mlx4_ib_dev *dev, struct ib_ucontext *cont
        int err;
 
        *umem = ib_umem_get(context, buf_addr, cqe * sizeof (struct mlx4_cqe),
-                           IB_ACCESS_LOCAL_WRITE);
+                           IB_ACCESS_LOCAL_WRITE, 1);
        if (IS_ERR(*umem))
                return PTR_ERR(*umem);
 
@@ -221,7 +221,7 @@ struct ib_cq *mlx4_ib_create_cq(struct ib_device *ibdev, int entries, int vector
        }
 
        err = mlx4_cq_alloc(dev->dev, entries, &cq->buf.mtt, uar,
-                           cq->db.dma, &cq->mcq);
+                           cq->db.dma, &cq->mcq, 0);
        if (err)
                goto err_dbmap;
 
index 8e342cc9baec95430033bf2019547c7a4d90d4e6..8aee4233b388e2938036567e43f78fa425cf0e30 100644 (file)
@@ -63,7 +63,7 @@ int mlx4_ib_db_map_user(struct mlx4_ib_ucontext *context, unsigned long virt,
        page->user_virt = (virt & PAGE_MASK);
        page->refcnt    = 0;
        page->umem      = ib_umem_get(&context->ibucontext, virt & PAGE_MASK,
-                                     PAGE_SIZE, 0);
+                                     PAGE_SIZE, 0, 0);
        if (IS_ERR(page->umem)) {
                err = PTR_ERR(page->umem);
                kfree(page);
index fe2c2e94a5f87031de3c68591c299b0c38bf353f..68e92485fc76f132ea079110691b1c283cd337e0 100644 (file)
@@ -132,7 +132,8 @@ struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
        if (!mr)
                return ERR_PTR(-ENOMEM);
 
-       mr->umem = ib_umem_get(pd->uobject->context, start, length, access_flags);
+       mr->umem = ib_umem_get(pd->uobject->context, start, length,
+                              access_flags, 0);
        if (IS_ERR(mr->umem)) {
                err = PTR_ERR(mr->umem);
                goto err_free;
index 80ea8b9e7761656cde75df7de58e33a50f3afdf3..8e02ecfec18872c4d8f5585cd01cf49c5c8b91b6 100644 (file)
@@ -482,7 +482,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
                        goto err;
 
                qp->umem = ib_umem_get(pd->uobject->context, ucmd.buf_addr,
-                                      qp->buf_size, 0);
+                                      qp->buf_size, 0, 0);
                if (IS_ERR(qp->umem)) {
                        err = PTR_ERR(qp->umem);
                        goto err;
index 204619702f9d7d9401bf5dd65012fbf2e0062de6..12d6bc6f8007da0ced4158b1a956c7da52bf56c0 100644 (file)
@@ -109,7 +109,7 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
                }
 
                srq->umem = ib_umem_get(pd->uobject->context, ucmd.buf_addr,
-                                       buf_size, 0);
+                                       buf_size, 0, 0);
                if (IS_ERR(srq->umem)) {
                        err = PTR_ERR(srq->umem);
                        goto err_srq;
index 3538da16e3fe9ec4cea862fa7b0100fb3d3225c7..820205dec560954562b22c570f7eb13861ec8824 100644 (file)
@@ -818,15 +818,9 @@ int mthca_arbel_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list,
 
 void mthca_tavor_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr)
 {
-       u32 key;
-
        if (!fmr->maps)
                return;
 
-       key = tavor_key_to_hw_index(fmr->ibmr.lkey);
-       key &= dev->limits.num_mpts - 1;
-       fmr->ibmr.lkey = fmr->ibmr.rkey = tavor_hw_index_to_key(key);
-
        fmr->maps = 0;
 
        writeb(MTHCA_MPT_STATUS_SW, fmr->mem.tavor.mpt);
@@ -834,16 +828,9 @@ void mthca_tavor_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr)
 
 void mthca_arbel_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr)
 {
-       u32 key;
-
        if (!fmr->maps)
                return;
 
-       key = arbel_key_to_hw_index(fmr->ibmr.lkey);
-       key &= dev->limits.num_mpts - 1;
-       key = adjust_key(dev, key);
-       fmr->ibmr.lkey = fmr->ibmr.rkey = arbel_hw_index_to_key(key);
-
        fmr->maps = 0;
 
        *(u8 *) fmr->mem.arbel.mpt = MTHCA_MPT_STATUS_SW;
index 696e1f30233268a6f69261ca10dd4fb0beadef28..be34f99ca62579b916970d5387110b370b99602d 100644 (file)
@@ -39,6 +39,8 @@
 #include <rdma/ib_smi.h>
 #include <rdma/ib_umem.h>
 #include <rdma/ib_user_verbs.h>
+
+#include <linux/sched.h>
 #include <linux/mm.h>
 
 #include "mthca_dev.h"
@@ -367,6 +369,8 @@ static struct ib_ucontext *mthca_alloc_ucontext(struct ib_device *ibdev,
                return ERR_PTR(-EFAULT);
        }
 
+       context->reg_mr_warned = 0;
+
        return &context->ibucontext;
 }
 
@@ -1006,17 +1010,31 @@ static struct ib_mr *mthca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
        struct mthca_dev *dev = to_mdev(pd->device);
        struct ib_umem_chunk *chunk;
        struct mthca_mr *mr;
+       struct mthca_reg_mr ucmd;
        u64 *pages;
        int shift, n, len;
        int i, j, k;
        int err = 0;
        int write_mtt_size;
 
+       if (udata->inlen - sizeof (struct ib_uverbs_cmd_hdr) < sizeof ucmd) {
+               if (!to_mucontext(pd->uobject->context)->reg_mr_warned) {
+                       mthca_warn(dev, "Process '%s' did not pass in MR attrs.\n",
+                                  current->comm);
+                       mthca_warn(dev, "  Update libmthca to fix this.\n");
+               }
+               ++to_mucontext(pd->uobject->context)->reg_mr_warned;
+               ucmd.mr_attrs = 0;
+       } else if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
+               return ERR_PTR(-EFAULT);
+
        mr = kmalloc(sizeof *mr, GFP_KERNEL);
        if (!mr)
                return ERR_PTR(-ENOMEM);
 
-       mr->umem = ib_umem_get(pd->uobject->context, start, length, acc);
+       mr->umem = ib_umem_get(pd->uobject->context, start, length, acc,
+                              ucmd.mr_attrs & MTHCA_MR_DMASYNC);
+
        if (IS_ERR(mr->umem)) {
                err = PTR_ERR(mr->umem);
                goto err;
index 262616c8ebb644d75ab603e5ce12b5f668baa5ac..934bf9544037c582aaeb60754d78ad534aef618c 100644 (file)
@@ -67,6 +67,7 @@ struct mthca_ucontext {
        struct ib_ucontext          ibucontext;
        struct mthca_uar            uar;
        struct mthca_user_db_table *db_tab;
+       int                         reg_mr_warned;
 };
 
 struct mthca_mtt;
index 02cc0a766f3ac767db1aba8333816ec58b402775..e1262c942db8c6ae31c91ec5b006454e239b2331 100644 (file)
@@ -61,6 +61,16 @@ struct mthca_alloc_pd_resp {
        __u32 reserved;
 };
 
+struct mthca_reg_mr {
+/*
+ * Mark the memory region with a DMA attribute that causes
+ * in-flight DMA to be flushed when the region is written to:
+ */
+#define MTHCA_MR_DMASYNC       0x1
+       __u32 mr_attrs;
+       __u32 reserved;
+};
+
 struct mthca_create_cq {
        __u32 lkey;
        __u32 pdn;
index 2aeb7ac972a9137d5d5f8ef47163032fbea418b3..d449eb6ec78e7d439a78cc824c260be16b32f93f 100644 (file)
@@ -2,6 +2,7 @@ config INFINIBAND_NES
        tristate "NetEffect RNIC Driver"
        depends on PCI && INET && INFINIBAND
        select LIBCRC32C
+       select INET_LRO
        ---help---
          This is a low-level driver for NetEffect RDMA enabled
          Network Interface Cards (RNIC).
index a4e9269a29bd106b604d1c8012efc25b4f1ab9c9..9f7364a9096d3d5b5ab42d07ee39ab4617f188cf 100644 (file)
@@ -91,6 +91,10 @@ unsigned int nes_debug_level = 0;
 module_param_named(debug_level, nes_debug_level, uint, 0644);
 MODULE_PARM_DESC(debug_level, "Enable debug output level");
 
+unsigned int nes_lro_max_aggr = NES_LRO_MAX_AGGR;
+module_param(nes_lro_max_aggr, int, NES_LRO_MAX_AGGR);
+MODULE_PARM_DESC(nes_mro_max_aggr, " nic LRO MAX packet aggregation");
+
 LIST_HEAD(nes_adapter_list);
 static LIST_HEAD(nes_dev_list);
 
index cdf2e9ad62f7512b59d601558ac53349f732552f..1f9f7bf73862a44d1cf0a4a2ac7d1e5099ef70bf 100644 (file)
@@ -173,6 +173,7 @@ extern int disable_mpa_crc;
 extern unsigned int send_first;
 extern unsigned int nes_drv_opt;
 extern unsigned int nes_debug_level;
+extern unsigned int nes_lro_max_aggr;
 
 extern struct list_head nes_adapter_list;
 
@@ -535,8 +536,8 @@ int nes_register_ofa_device(struct nes_ib_device *);
 int nes_read_eeprom_values(struct nes_device *, struct nes_adapter *);
 void nes_write_1G_phy_reg(struct nes_device *, u8, u8, u16);
 void nes_read_1G_phy_reg(struct nes_device *, u8, u8, u16 *);
-void nes_write_10G_phy_reg(struct nes_device *, u16, u8, u16);
-void nes_read_10G_phy_reg(struct nes_device *, u16, u8);
+void nes_write_10G_phy_reg(struct nes_device *, u16, u8, u16, u16);
+void nes_read_10G_phy_reg(struct nes_device *, u8, u8, u16);
 struct nes_cqp_request *nes_get_cqp_request(struct nes_device *);
 void nes_post_cqp_request(struct nes_device *, struct nes_cqp_request *, int);
 int nes_arp_table(struct nes_device *, u32, u8 *, u32);
index d940fc27129afdc37e3457115eb58fb8a5ab25ef..9a4b40fae40db3c8994daf5ea66a5cfcfd3b55b5 100644 (file)
@@ -594,7 +594,7 @@ static void nes_cm_timer_tick(unsigned long pass)
                                continue;
                        }
                        /* this seems like the correct place, but leave send entry unprotected */
-                       // spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
+                       /* spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); */
                        atomic_inc(&send_entry->skb->users);
                        cm_packets_retrans++;
                        nes_debug(NES_DBG_CM, "Retransmitting send_entry %p for node %p,"
@@ -1335,7 +1335,7 @@ static int process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
                                                        cm_node->loc_addr, cm_node->loc_port,
                                                        cm_node->rem_addr, cm_node->rem_port,
                                                        cm_node->state, atomic_read(&cm_node->ref_count));
-                               // create event
+                               /* create event */
                                cm_node->state = NES_CM_STATE_CLOSED;
 
                                create_event(cm_node, NES_CM_EVENT_ABORTED);
@@ -1669,7 +1669,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
        if (!cm_node)
                return NULL;
 
-       // set our node side to client (active) side
+       /* set our node side to client (active) side */
        cm_node->tcp_cntxt.client = 1;
        cm_node->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE;
 
@@ -1694,7 +1694,7 @@ static struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
                        loopbackremotenode->mpa_frame_size = mpa_frame_size -
                                        sizeof(struct ietf_mpa_frame);
 
-                       // we are done handling this state, set node to a TSA state
+                       /* we are done handling this state, set node to a TSA state */
                        cm_node->state = NES_CM_STATE_TSA;
                        cm_node->tcp_cntxt.rcv_nxt = loopbackremotenode->tcp_cntxt.loc_seq_num;
                        loopbackremotenode->tcp_cntxt.rcv_nxt = cm_node->tcp_cntxt.loc_seq_num;
index 08964cc7e98aead2bc4813c8505d1abdbafc2bc2..8dc70f9bad2f49f828b95dca4544ec46c1aa95b2 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/if_vlan.h>
+#include <linux/inet_lro.h>
 
 #include "nes.h"
 
@@ -832,7 +833,7 @@ static void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_cou
        nes_write_indexed(nesdev, 0x00000900, 0x20000001);
        nes_write_indexed(nesdev, 0x000060C0, 0x0000028e);
        nes_write_indexed(nesdev, 0x000060C8, 0x00000020);
-                                                                                                               //
+
        nes_write_indexed(nesdev, 0x000001EC, 0x7b2625a0);
        /* nes_write_indexed(nesdev, 0x000001EC, 0x5f2625a0); */
 
@@ -1207,11 +1208,16 @@ int nes_init_phy(struct nes_device *nesdev)
 {
        struct nes_adapter *nesadapter = nesdev->nesadapter;
        u32 counter = 0;
+       u32 sds_common_control0;
        u32 mac_index = nesdev->mac_index;
-       u32 tx_config;
+       u32 tx_config = 0;
        u16 phy_data;
+       u32 temp_phy_data = 0;
+       u32 temp_phy_data2 = 0;
+       u32 i = 0;
 
-       if (nesadapter->OneG_Mode) {
+       if ((nesadapter->OneG_Mode) &&
+           (nesadapter->phy_type[mac_index] != NES_PHY_TYPE_PUMA_1G)) {
                nes_debug(NES_DBG_PHY, "1G PHY, mac_index = %d.\n", mac_index);
                if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_1G) {
                        printk(PFX "%s: Programming mdc config for 1G\n", __func__);
@@ -1223,7 +1229,7 @@ int nes_init_phy(struct nes_device *nesdev)
                nes_read_1G_phy_reg(nesdev, 1, nesadapter->phy_index[mac_index], &phy_data);
                nes_debug(NES_DBG_PHY, "Phy data from register 1 phy address %u = 0x%X.\n",
                                nesadapter->phy_index[mac_index], phy_data);
-               nes_write_1G_phy_reg(nesdev, 23, nesadapter->phy_index[mac_index],  0xb000);
+               nes_write_1G_phy_reg(nesdev, 23, nesadapter->phy_index[mac_index], 0xb000);
 
                /* Reset the PHY */
                nes_write_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], 0x8000);
@@ -1277,12 +1283,126 @@ int nes_init_phy(struct nes_device *nesdev)
                nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], &phy_data);
                nes_write_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], phy_data | 0x0300);
        } else {
-               if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_IRIS) {
+               if ((nesadapter->phy_type[mac_index] == NES_PHY_TYPE_IRIS) ||
+                   (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_ARGUS)) {
                        /* setup 10G MDIO operation */
                        tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);
                        tx_config |= 0x14;
                        nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);
                }
+               if ((nesadapter->phy_type[mac_index] == NES_PHY_TYPE_ARGUS)) {
+                       nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0xd7ee);
+
+                       temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+                       mdelay(10);
+                       nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0xd7ee);
+                       temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+
+                       /*
+                        * if firmware is already running (like from a
+                        * driver un-load/load, don't do anything.
+                        */
+                       if (temp_phy_data == temp_phy_data2) {
+                               /* configure QT2505 AMCC PHY */
+                               nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0x0000, 0x8000);
+                               nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc300, 0x0000);
+                               nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc302, 0x0044);
+                               nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc318, 0x0052);
+                               nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc319, 0x0008);
+                               nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc31a, 0x0098);
+                               nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0026, 0x0E00);
+                               nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0027, 0x0000);
+                               nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0x0028, 0xA528);
+
+                               /*
+                                * remove micro from reset; chip boots from ROM,
+                                * uploads EEPROM f/w image, uC executes f/w
+                                */
+                               nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc300, 0x0002);
+
+                               /*
+                                * wait for heart beat to start to
+                                * know loading is done
+                                */
+                               counter = 0;
+                               do {
+                                       nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0xd7ee);
+                                       temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+                                       if (counter++ > 1000) {
+                                               nes_debug(NES_DBG_PHY, "AMCC PHY- breaking from heartbeat check <this is bad!!!> \n");
+                                               break;
+                                       }
+                                       mdelay(100);
+                                       nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0xd7ee);
+                                       temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+                               } while ((temp_phy_data2 == temp_phy_data));
+
+                               /*
+                                * wait for tracking to start to know
+                                * f/w is good to go
+                                */
+                               counter = 0;
+                               do {
+                                       nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x3, 0xd7fd);
+                                       temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+                                       if (counter++ > 1000) {
+                                               nes_debug(NES_DBG_PHY, "AMCC PHY- breaking from status check <this is bad!!!> \n");
+                                               break;
+                                       }
+                                       mdelay(1000);
+                                       /*
+                                        * nes_debug(NES_DBG_PHY, "AMCC PHY- phy_status not ready yet = 0x%02X\n",
+                                        *                      temp_phy_data);
+                                        */
+                               } while (((temp_phy_data & 0xff) != 0x50) && ((temp_phy_data & 0xff) != 0x70));
+
+                               /* set LOS Control invert RXLOSB_I_PADINV */
+                               nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xd003, 0x0000);
+                               /* set LOS Control to mask of RXLOSB_I */
+                               nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xc314, 0x0042);
+                               /* set LED1 to input mode (LED1 and LED2 share same LED) */
+                               nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xd006, 0x0007);
+                               /* set LED2 to RX link_status and activity */
+                               nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xd007, 0x000A);
+                               /* set LED3 to RX link_status */
+                               nes_write_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 0x1, 0xd008, 0x0009);
+
+                               /*
+                                * reset the res-calibration on t2
+                                * serdes; ensures it is stable after
+                                * the amcc phy is stable
+                                */
+
+                               sds_common_control0  = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0);
+                               sds_common_control0 |= 0x1;
+                               nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, sds_common_control0);
+
+                               /* release the res-calibration reset */
+                               sds_common_control0 &= 0xfffffffe;
+                               nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, sds_common_control0);
+
+                               i = 0;
+                               while (((nes_read32(nesdev->regs + NES_SOFTWARE_RESET) & 0x00000040) != 0x00000040)
+                                               && (i++ < 5000)) {
+                                       /* mdelay(1); */
+                               }
+
+                               /*
+                                * wait for link train done before moving on,
+                                * or will get an interupt storm
+                                */
+                               counter = 0;
+                               do {
+                                       temp_phy_data = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
+                                                               (0x200 * (nesdev->mac_index & 1)));
+                                       if (counter++ > 1000) {
+                                               nes_debug(NES_DBG_PHY, "AMCC PHY- breaking from link train wait <this is bad, link didnt train!!!>\n");
+                                               break;
+                                       }
+                                       mdelay(1);
+                               } while (((temp_phy_data & 0x0f1f0000) != 0x0f0f0000));
+                       }
+               }
        }
        return 0;
 }
@@ -1375,6 +1495,25 @@ static void nes_rq_wqes_timeout(unsigned long parm)
 }
 
 
+static int nes_lro_get_skb_hdr(struct sk_buff *skb, void **iphdr,
+                              void **tcph, u64 *hdr_flags, void *priv)
+{
+       unsigned int ip_len;
+       struct iphdr *iph;
+       skb_reset_network_header(skb);
+       iph = ip_hdr(skb);
+       if (iph->protocol != IPPROTO_TCP)
+               return -1;
+       ip_len = ip_hdrlen(skb);
+       skb_set_transport_header(skb, ip_len);
+       *tcph = tcp_hdr(skb);
+
+       *hdr_flags = LRO_IPV4 | LRO_TCP;
+       *iphdr = iph;
+       return 0;
+}
+
+
 /**
  * nes_init_nic_qp
  */
@@ -1520,10 +1659,10 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
        }
 
        u64temp = (u64)nesvnic->nic.sq_pbase;
-       nic_context->context_words[NES_NIC_CTX_SQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
+       nic_context->context_words[NES_NIC_CTX_SQ_LOW_IDX]  = cpu_to_le32((u32)u64temp);
        nic_context->context_words[NES_NIC_CTX_SQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
        u64temp = (u64)nesvnic->nic.rq_pbase;
-       nic_context->context_words[NES_NIC_CTX_RQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
+       nic_context->context_words[NES_NIC_CTX_RQ_LOW_IDX]  = cpu_to_le32((u32)u64temp);
        nic_context->context_words[NES_NIC_CTX_RQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
 
        cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_CREATE_QP |
@@ -1575,7 +1714,7 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
                nic_rqe = &nesvnic->nic.rq_vbase[counter];
                nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = cpu_to_le32(nesvnic->max_frame_size);
                nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;
-               nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] = cpu_to_le32((u32)pmem);
+               nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]  = cpu_to_le32((u32)pmem);
                nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] = cpu_to_le32((u32)((u64)pmem >> 32));
                nesvnic->nic.rx_skb[counter] = skb;
        }
@@ -1592,15 +1731,21 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
        nesvnic->rq_wqes_timer.function = nes_rq_wqes_timeout;
        nesvnic->rq_wqes_timer.data = (unsigned long)nesvnic;
        nes_debug(NES_DBG_INIT, "NAPI support Enabled\n");
-
        if (nesdev->nesadapter->et_use_adaptive_rx_coalesce)
        {
                nes_nic_init_timer(nesdev);
                if (netdev->mtu > 1500)
                        jumbomode = 1;
-                nes_nic_init_timer_defaults(nesdev, jumbomode);
-       }
-
+               nes_nic_init_timer_defaults(nesdev, jumbomode);
+       }
+       nesvnic->lro_mgr.max_aggr       = NES_LRO_MAX_AGGR;
+       nesvnic->lro_mgr.max_desc       = NES_MAX_LRO_DESCRIPTORS;
+       nesvnic->lro_mgr.lro_arr        = nesvnic->lro_desc;
+       nesvnic->lro_mgr.get_skb_header = nes_lro_get_skb_hdr;
+       nesvnic->lro_mgr.features       = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;
+       nesvnic->lro_mgr.dev            = netdev;
+       nesvnic->lro_mgr.ip_summed      = CHECKSUM_UNNECESSARY;
+       nesvnic->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
        return 0;
 }
 
@@ -1620,8 +1765,8 @@ void nes_destroy_nic_qp(struct nes_vnic *nesvnic)
 
        /* Free remaining NIC receive buffers */
        while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) {
-               nic_rqe = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail];
-               wqe_frag = (u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
+               nic_rqe   = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail];
+               wqe_frag  = (u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
                wqe_frag |= ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32;
                pci_unmap_single(nesdev->pcidev, (dma_addr_t)wqe_frag,
                                nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
@@ -1704,17 +1849,17 @@ int nes_napi_isr(struct nes_device *nesdev)
        /* iff NIC, process here, else wait for DPC */
        if ((int_stat) && ((int_stat & 0x0000ff00) == int_stat)) {
                nesdev->napi_isr_ran = 0;
-               nes_write32(nesdev->regs+NES_INT_STAT,
-                               (int_stat &
-                               ~(NES_INT_INTF|NES_INT_TIMER|NES_INT_MAC0|NES_INT_MAC1|NES_INT_MAC2|NES_INT_MAC3)));
+               nes_write32(nesdev->regs + NES_INT_STAT,
+                       (int_stat &
+                       ~(NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0 | NES_INT_MAC1 | NES_INT_MAC2 | NES_INT_MAC3)));
 
                /* Process the CEQs */
                nes_process_ceq(nesdev, &nesdev->nesadapter->ceq[nesdev->nic_ceq_index]);
 
                if (unlikely((((nesadapter->et_rx_coalesce_usecs_irq) &&
-                                          (!nesadapter->et_use_adaptive_rx_coalesce)) ||
-                                         ((nesadapter->et_use_adaptive_rx_coalesce) &&
-                                          (nesdev->deepcq_count > nesadapter->et_pkt_rate_low)))) ) {
+                                       (!nesadapter->et_use_adaptive_rx_coalesce)) ||
+                                       ((nesadapter->et_use_adaptive_rx_coalesce) &&
+                                        (nesdev->deepcq_count > nesadapter->et_pkt_rate_low))))) {
                        if ((nesdev->int_req & NES_INT_TIMER) == 0) {
                                /* Enable Periodic timer interrupts */
                                nesdev->int_req |= NES_INT_TIMER;
@@ -1792,12 +1937,12 @@ void nes_dpc(unsigned long param)
                }
 
                if (int_stat) {
-                       if (int_stat & ~(NES_INT_INTF|NES_INT_TIMER|NES_INT_MAC0|
-                                       NES_INT_MAC1|NES_INT_MAC2|NES_INT_MAC3)) {
+                       if (int_stat & ~(NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0|
+                                       NES_INT_MAC1|NES_INT_MAC2 | NES_INT_MAC3)) {
                                /* Ack the interrupts */
                                nes_write32(nesdev->regs+NES_INT_STAT,
-                                               (int_stat & ~(NES_INT_INTF|NES_INT_TIMER|NES_INT_MAC0|
-                                               NES_INT_MAC1|NES_INT_MAC2|NES_INT_MAC3)));
+                                       (int_stat & ~(NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0|
+                                       NES_INT_MAC1 | NES_INT_MAC2 | NES_INT_MAC3)));
                        }
 
                        temp_int_stat = int_stat;
@@ -1862,8 +2007,8 @@ void nes_dpc(unsigned long param)
                        }
                }
                /* Don't use the interface interrupt bit stay in loop */
-               int_stat &= ~NES_INT_INTF|NES_INT_TIMER|NES_INT_MAC0|
-                               NES_INT_MAC1|NES_INT_MAC2|NES_INT_MAC3;
+               int_stat &= ~NES_INT_INTF | NES_INT_TIMER | NES_INT_MAC0 |
+                               NES_INT_MAC1 | NES_INT_MAC2 | NES_INT_MAC3;
        } while ((int_stat != 0) && (loop_counter++ < MAX_DPC_ITERATIONS));
 
        if (timer_ints == 1) {
@@ -1874,9 +2019,9 @@ void nes_dpc(unsigned long param)
                                        nesdev->timer_only_int_count = 0;
                                        nesdev->int_req &= ~NES_INT_TIMER;
                                        nes_write32(nesdev->regs + NES_INTF_INT_MASK, ~(nesdev->intf_int_req));
-                                       nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req);
+                                       nes_write32(nesdev->regs + NES_INT_MASK, ~nesdev->int_req);
                                } else {
-                                       nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff|(~nesdev->int_req));
+                                       nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));
                                }
                        } else {
                                if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))
@@ -1884,7 +2029,7 @@ void nes_dpc(unsigned long param)
                                        nes_nic_init_timer(nesdev);
                                }
                                nesdev->timer_only_int_count = 0;
-                               nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff|(~nesdev->int_req));
+                               nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));
                        }
                } else {
                        nesdev->timer_only_int_count = 0;
@@ -1933,7 +2078,7 @@ static void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq)
        do {
                if (le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX]) &
                                NES_CEQE_VALID) {
-                       u64temp = (((u64)(le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX])))<<32) |
+                       u64temp = (((u64)(le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX]))) << 32) |
                                                ((u64)(le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_LOW_IDX])));
                        u64temp <<= 1;
                        cq = *((struct nes_hw_cq **)&u64temp);
@@ -1961,7 +2106,7 @@ static void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq)
  */
 static void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq)
 {
-//     u64 u64temp;
+       /* u64 u64temp; */
        u32 head;
        u32 aeq_size;
        u32 aeqe_misc;
@@ -1980,8 +2125,10 @@ static void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq)
                if (aeqe_misc & (NES_AEQE_QP|NES_AEQE_CQ)) {
                        if (aeqe_cq_id >= NES_FIRST_QPN) {
                                /* dealing with an accelerated QP related AE */
-//                             u64temp = (((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])))<<32) |
-//                                     ((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX])));
+                               /*
+                                * u64temp = (((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX]))) << 32) |
+                                *           ((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX])));
+                                */
                                nes_process_iwarp_aeqe(nesdev, (struct nes_hw_aeqe *)aeqe);
                        } else {
                                /* TODO: dealing with a CQP related AE */
@@ -2081,6 +2228,8 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
        u32 u32temp;
        u16 phy_data;
        u16 temp_phy_data;
+       u32 pcs_val  = 0x0f0f0000;
+       u32 pcs_mask = 0x0f1f0000;
 
        spin_lock_irqsave(&nesadapter->phy_lock, flags);
        if (nesadapter->mac_sw_state[mac_number] != NES_MAC_SW_IDLE) {
@@ -2144,13 +2293,30 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
                nes_debug(NES_DBG_PHY, "Eth SERDES Common Status: 0=0x%08X, 1=0x%08X\n",
                                nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0),
                                nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0+0x200));
-               pcs_control_status = nes_read_indexed(nesdev,
-                               NES_IDX_PHY_PCS_CONTROL_STATUS0 + ((mac_index&1)*0x200));
-               pcs_control_status = nes_read_indexed(nesdev,
-                               NES_IDX_PHY_PCS_CONTROL_STATUS0 + ((mac_index&1)*0x200));
+
+               if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_PUMA_1G) {
+                       switch (mac_index) {
+                       case 1:
+                       case 3:
+                               pcs_control_status = nes_read_indexed(nesdev,
+                                               NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
+                               break;
+                       default:
+                               pcs_control_status = nes_read_indexed(nesdev,
+                                               NES_IDX_PHY_PCS_CONTROL_STATUS0);
+                               break;
+                       }
+               } else {
+                       pcs_control_status = nes_read_indexed(nesdev,
+                                       NES_IDX_PHY_PCS_CONTROL_STATUS0 + ((mac_index & 1) * 0x200));
+                       pcs_control_status = nes_read_indexed(nesdev,
+                                       NES_IDX_PHY_PCS_CONTROL_STATUS0 + ((mac_index & 1) * 0x200));
+               }
+
                nes_debug(NES_DBG_PHY, "PCS PHY Control/Status%u: 0x%08X\n",
                                mac_index, pcs_control_status);
-               if (nesadapter->OneG_Mode) {
+               if ((nesadapter->OneG_Mode) &&
+                               (nesadapter->phy_type[mac_index] != NES_PHY_TYPE_PUMA_1G)) {
                        u32temp = 0x01010000;
                        if (nesadapter->port_count > 2) {
                                u32temp |= 0x02020000;
@@ -2159,24 +2325,59 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
                                phy_data = 0;
                                nes_debug(NES_DBG_PHY, "PCS says the link is down\n");
                        }
-               } else if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_IRIS) {
-                       nes_read_10G_phy_reg(nesdev, 1, nesadapter->phy_index[mac_index]);
-                       temp_phy_data = (u16)nes_read_indexed(nesdev,
-                                                               NES_IDX_MAC_MDIO_CONTROL);
-                       u32temp = 20;
-                       do {
-                               nes_read_10G_phy_reg(nesdev, 1, nesadapter->phy_index[mac_index]);
-                               phy_data = (u16)nes_read_indexed(nesdev,
-                                                               NES_IDX_MAC_MDIO_CONTROL);
-                               if ((phy_data == temp_phy_data) || (!(--u32temp)))
-                                       break;
-                               temp_phy_data = phy_data;
-                       } while (1);
-                       nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n",
-                               __func__, phy_data, nesadapter->mac_link_down ? "DOWN" : "UP");
-
                } else {
-                       phy_data = (0x0f0f0000 == (pcs_control_status & 0x0f1f0000)) ? 4 : 0;
+                       switch (nesadapter->phy_type[mac_index]) {
+                       case NES_PHY_TYPE_IRIS:
+                               nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 1);
+                               temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+                               u32temp = 20;
+                               do {
+                                       nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 1);
+                                       phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+                                       if ((phy_data == temp_phy_data) || (!(--u32temp)))
+                                               break;
+                                       temp_phy_data = phy_data;
+                               } while (1);
+                               nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n",
+                                       __func__, phy_data, nesadapter->mac_link_down[mac_index] ? "DOWN" : "UP");
+                               break;
+
+                       case NES_PHY_TYPE_ARGUS:
+                               /* clear the alarms */
+                               nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0x0008);
+                               nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc001);
+                               nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc002);
+                               nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc005);
+                               nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 4, 0xc006);
+                               nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9003);
+                               nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9004);
+                               nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9005);
+                               /* check link status */
+                               nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 1);
+                               temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+                               u32temp = 100;
+                               do {
+                                       nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 1);
+
+                                       phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
+                                       if ((phy_data == temp_phy_data) || (!(--u32temp)))
+                                               break;
+                                       temp_phy_data = phy_data;
+                               } while (1);
+                               nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n",
+                                       __func__, phy_data, nesadapter->mac_link_down ? "DOWN" : "UP");
+                               break;
+
+                       case NES_PHY_TYPE_PUMA_1G:
+                               if (mac_index < 2)
+                                       pcs_val = pcs_mask = 0x01010000;
+                               else
+                                       pcs_val = pcs_mask = 0x02020000;
+                               /* fall through */
+                       default:
+                               phy_data = (pcs_val == (pcs_control_status & pcs_mask)) ? 0x4 : 0x0;
+                               break;
+                       }
                }
 
                if (phy_data & 0x0004) {
@@ -2185,8 +2386,8 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
                                nes_debug(NES_DBG_PHY, "The Link is UP!!.  linkup was %d\n",
                                                nesvnic->linkup);
                                if (nesvnic->linkup == 0) {
-                                       printk(PFX "The Link is now up for port %u, netdev %p.\n",
-                                                       mac_index, nesvnic->netdev);
+                                       printk(PFX "The Link is now up for port %s, netdev %p.\n",
+                                                       nesvnic->netdev->name, nesvnic->netdev);
                                        if (netif_queue_stopped(nesvnic->netdev))
                                                netif_start_queue(nesvnic->netdev);
                                        nesvnic->linkup = 1;
@@ -2199,8 +2400,8 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
                                nes_debug(NES_DBG_PHY, "The Link is Down!!. linkup was %d\n",
                                                nesvnic->linkup);
                                if (nesvnic->linkup == 1) {
-                                       printk(PFX "The Link is now down for port %u, netdev %p.\n",
-                                                       mac_index, nesvnic->netdev);
+                                       printk(PFX "The Link is now down for port %s, netdev %p.\n",
+                                                       nesvnic->netdev->name, nesvnic->netdev);
                                        if (!(netif_queue_stopped(nesvnic->netdev)))
                                                netif_stop_queue(nesvnic->netdev);
                                        nesvnic->linkup = 0;
@@ -2254,10 +2455,13 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
        u16 pkt_type;
        u16 rqes_processed = 0;
        u8 sq_cqes = 0;
+       u8 nes_use_lro = 0;
 
        head = cq->cq_head;
        cq_size = cq->cq_size;
        cq->cqes_pending = 1;
+       if (nesvnic->netdev->features & NETIF_F_LRO)
+               nes_use_lro = 1;
        do {
                if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]) &
                                NES_NIC_CQE_VALID) {
@@ -2272,8 +2476,10 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
                                /* bump past the vlan tag */
                                wqe_fragment_length++;
                                if (le16_to_cpu(wqe_fragment_length[wqe_fragment_index]) != 0) {
-                                       u64temp = (u64) le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX+wqe_fragment_index*2]);
-                                       u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX+wqe_fragment_index*2]))<<32;
+                                       u64temp = (u64) le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX +
+                                                       wqe_fragment_index * 2]);
+                                       u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX +
+                                                       wqe_fragment_index * 2])) << 32;
                                        bus_address = (dma_addr_t)u64temp;
                                        if (test_and_clear_bit(nesnic->sq_tail, nesnic->first_frag_overflow)) {
                                                pci_unmap_single(nesdev->pcidev,
@@ -2283,8 +2489,10 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
                                        }
                                        for (; wqe_fragment_index < 5; wqe_fragment_index++) {
                                                if (wqe_fragment_length[wqe_fragment_index]) {
-                                                       u64temp = le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX+wqe_fragment_index*2]);
-                                                       u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX+wqe_fragment_index*2]))<<32;
+                                                       u64temp = le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX +
+                                                                               wqe_fragment_index * 2]);
+                                                       u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX
+                                                                               + wqe_fragment_index * 2])) <<32;
                                                        bus_address = (dma_addr_t)u64temp;
                                                        pci_unmap_page(nesdev->pcidev,
                                                                        bus_address,
@@ -2331,7 +2539,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
                                if (atomic_read(&nesvnic->rx_skbs_needed) > (nesvnic->nic.rq_size>>1)) {
                                        nes_write32(nesdev->regs+NES_CQE_ALLOC,
                                                        cq->cq_number | (cqe_count << 16));
-//                                     nesadapter->tune_timer.cq_count += cqe_count;
+                                       /* nesadapter->tune_timer.cq_count += cqe_count; */
                                        nesdev->currcq_count += cqe_count;
                                        cqe_count = 0;
                                        nes_replenish_nic_rq(nesvnic);
@@ -2379,9 +2587,16 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
                                                                >> 16);
                                                nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n",
                                                                nesvnic->netdev->name, vlan_tag);
-                                               nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag);
+                                               if (nes_use_lro)
+                                                       lro_vlan_hwaccel_receive_skb(&nesvnic->lro_mgr, rx_skb,
+                                                                       nesvnic->vlan_grp, vlan_tag, NULL);
+                                               else
+                                                       nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag);
                                        } else {
-                                               nes_netif_rx(rx_skb);
+                                               if (nes_use_lro)
+                                                       lro_receive_skb(&nesvnic->lro_mgr, rx_skb, NULL);
+                                               else
+                                                       nes_netif_rx(rx_skb);
                                        }
                                }
 
@@ -2399,7 +2614,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
                                /* Replenish Nic CQ */
                                nes_write32(nesdev->regs+NES_CQE_ALLOC,
                                                cq->cq_number | (cqe_count << 16));
-//                             nesdev->nesadapter->tune_timer.cq_count += cqe_count;
+                               /* nesdev->nesadapter->tune_timer.cq_count += cqe_count; */
                                nesdev->currcq_count += cqe_count;
                                cqe_count = 0;
                        }
@@ -2413,26 +2628,27 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
 
        } while (1);
 
+       if (nes_use_lro)
+               lro_flush_all(&nesvnic->lro_mgr);
        if (sq_cqes) {
                barrier();
                /* restart the queue if it had been stopped */
                if (netif_queue_stopped(nesvnic->netdev))
                        netif_wake_queue(nesvnic->netdev);
        }
-
        cq->cq_head = head;
        /* nes_debug(NES_DBG_CQ, "CQ%u Processed = %u cqes, new head = %u.\n",
                        cq->cq_number, cqe_count, cq->cq_head); */
        cq->cqe_allocs_pending = cqe_count;
        if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))
        {
-//             nesdev->nesadapter->tune_timer.cq_count += cqe_count;
+               /* nesdev->nesadapter->tune_timer.cq_count += cqe_count; */
                nesdev->currcq_count += cqe_count;
                nes_nic_tune_timer(nesdev);
        }
        if (atomic_read(&nesvnic->rx_skbs_needed))
                nes_replenish_nic_rq(nesvnic);
-       }
+}
 
 
 /**
@@ -2461,7 +2677,7 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
 
                if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) {
                        u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].
-                                       cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX])))<<32) |
+                                       cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX]))) << 32) |
                                        ((u64)(le32_to_cpu(cq->cq_vbase[head].
                                        cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
                        cqp = *((struct nes_hw_cqp **)&u64temp);
@@ -2478,7 +2694,7 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
                        }
 
                        u64temp = (((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
-                                       wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX])))<<32) |
+                                       wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) |
                                        ((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
                                        wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX])));
                        cqp_request = *((struct nes_cqp_request **)&u64temp);
@@ -2515,7 +2731,7 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
                                } else {
                                        nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) freed.\n",
                                                        cqp_request,
-                                                       le32_to_cpu(cqp_request->cqp_wqe.wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f);
+                                                       le32_to_cpu(cqp_request->cqp_wqe.wqe_words[NES_CQP_WQE_OPCODE_IDX]) & 0x3f);
                                        if (cqp_request->dynamic) {
                                                kfree(cqp_request);
                                        } else {
@@ -2529,7 +2745,7 @@ static void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
                        }
 
                        cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX] = 0;
-                       nes_write32(nesdev->regs+NES_CQE_ALLOC, cq->cq_number | (1 << 16));
+                       nes_write32(nesdev->regs + NES_CQE_ALLOC, cq->cq_number | (1 << 16));
                        if (++cqp->sq_tail >= cqp->sq_size)
                                cqp->sq_tail = 0;
 
@@ -2598,13 +2814,13 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
        nes_debug(NES_DBG_AEQ, "\n");
        aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);
        if ((NES_AEQE_INBOUND_RDMA&aeq_info) || (!(NES_AEQE_QP&aeq_info))) {
-               context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]);
+               context  = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]);
                context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32;
        } else {
                aeqe_context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]);
                aeqe_context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32;
                context = (unsigned long)nesadapter->qp_table[le32_to_cpu(
-                                               aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN];
+                                               aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]) - NES_FIRST_QPN];
                BUG_ON(!context);
        }
 
@@ -2617,7 +2833,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
                        le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]), aeqe,
                        nes_tcp_state_str[tcp_state], nes_iwarp_state_str[iwarp_state]);
 
-
        switch (async_event_id) {
                case NES_AEQE_AEID_LLP_FIN_RECEIVED:
                        nesqp = *((struct nes_qp **)&context);
@@ -3021,7 +3236,7 @@ void nes_manage_arp_cache(struct net_device *netdev, unsigned char *mac_addr,
                cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(NES_CQP_ARP_VALID);
                cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = cpu_to_le32(
                                (((u32)mac_addr[2]) << 24) | (((u32)mac_addr[3]) << 16) |
-                               (((u32)mac_addr[4]) << 8) | (u32)mac_addr[5]);
+                               (((u32)mac_addr[4]) << 8)  | (u32)mac_addr[5]);
                cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = cpu_to_le32(
                                (((u32)mac_addr[0]) << 16) | (u32)mac_addr[1]);
        } else {
index 8f36e231bdf5db1e54e54a2707fb0bd12b165d0c..745bf94f3f074283f9c6f9dc36547f976d64883e 100644 (file)
 #ifndef __NES_HW_H
 #define __NES_HW_H
 
-#define NES_PHY_TYPE_1G   2
-#define NES_PHY_TYPE_IRIS 3
+#include <linux/inet_lro.h>
+
+#define NES_PHY_TYPE_1G        2
+#define NES_PHY_TYPE_IRIS      3
+#define NES_PHY_TYPE_ARGUS     4
+#define NES_PHY_TYPE_PUMA_1G   5
 #define NES_PHY_TYPE_PUMA_10G  6
 
 #define NES_MULTICAST_PF_MAX 8
@@ -965,7 +969,7 @@ struct nes_arp_entry {
 #define NES_NIC_CQ_DOWNWARD_TREND   16
 
 struct nes_hw_tune_timer {
-    //u16 cq_count;
+    /* u16 cq_count; */
     u16 threshold_low;
     u16 threshold_target;
     u16 threshold_high;
@@ -982,8 +986,10 @@ struct nes_hw_tune_timer {
 #define NES_TIMER_INT_LIMIT         2
 #define NES_TIMER_INT_LIMIT_DYNAMIC 10
 #define NES_TIMER_ENABLE_LIMIT      4
-#define NES_MAX_LINK_INTERRUPTS                128
-#define NES_MAX_LINK_CHECK             200
+#define NES_MAX_LINK_INTERRUPTS     128
+#define NES_MAX_LINK_CHECK          200
+#define NES_MAX_LRO_DESCRIPTORS     32
+#define NES_LRO_MAX_AGGR            64
 
 struct nes_adapter {
        u64              fw_ver;
@@ -1183,6 +1189,9 @@ struct nes_vnic {
        u8  of_device_registered;
        u8  rdma_enabled;
        u8  rx_checksum_disabled;
+       u32 lro_max_aggr;
+       struct net_lro_mgr lro_mgr;
+       struct net_lro_desc lro_desc[NES_MAX_LRO_DESCRIPTORS];
 };
 
 struct nes_ib_device {
index e5366b013c1afc472c8f295f56791d21663e424a..1b0938c87774e54017dd22364520778547b40dee 100644 (file)
@@ -185,12 +185,13 @@ static int nes_netdev_open(struct net_device *netdev)
        nic_active |= nic_active_bit;
        nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active);
 
-       macaddr_high = ((u16)netdev->dev_addr[0]) << 8;
+       macaddr_high  = ((u16)netdev->dev_addr[0]) << 8;
        macaddr_high += (u16)netdev->dev_addr[1];
-       macaddr_low = ((u32)netdev->dev_addr[2]) << 24;
-       macaddr_low += ((u32)netdev->dev_addr[3]) << 16;
-       macaddr_low += ((u32)netdev->dev_addr[4]) << 8;
-       macaddr_low += (u32)netdev->dev_addr[5];
+
+       macaddr_low   = ((u32)netdev->dev_addr[2]) << 24;
+       macaddr_low  += ((u32)netdev->dev_addr[3]) << 16;
+       macaddr_low  += ((u32)netdev->dev_addr[4]) << 8;
+       macaddr_low  += (u32)netdev->dev_addr[5];
 
        /* Program the various MAC regs */
        for (i = 0; i < NES_MAX_PORT_COUNT; i++) {
@@ -451,7 +452,7 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev)
        __le16 *wqe_fragment_length;
        u32 nr_frags;
        u32 original_first_length;
-//     u64 *wqe_fragment_address;
+       /* u64 *wqe_fragment_address; */
        /* first fragment (0) is used by copy buffer */
        u16 wqe_fragment_index=1;
        u16 hoffset;
@@ -461,11 +462,12 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev)
        u32 old_head;
        u32 wqe_misc;
 
-       /* nes_debug(NES_DBG_NIC_TX, "%s Request to tx NIC packet length %u, headlen %u,"
-                       " (%u frags), tso_size=%u\n",
-                       netdev->name, skb->len, skb_headlen(skb),
-                       skb_shinfo(skb)->nr_frags, skb_is_gso(skb));
-       */
+       /*
+        * nes_debug(NES_DBG_NIC_TX, "%s Request to tx NIC packet length %u, headlen %u,"
+        *              " (%u frags), tso_size=%u\n",
+        *              netdev->name, skb->len, skb_headlen(skb),
+        *              skb_shinfo(skb)->nr_frags, skb_is_gso(skb));
+        */
 
        if (!netif_carrier_ok(netdev))
                return NETDEV_TX_OK;
@@ -795,12 +797,12 @@ static int nes_netdev_set_mac_address(struct net_device *netdev, void *p)
        memcpy(netdev->dev_addr, mac_addr->sa_data, netdev->addr_len);
        printk(PFX "%s: Address length = %d, Address = %s\n",
               __func__, netdev->addr_len, print_mac(mac, mac_addr->sa_data));
-       macaddr_high = ((u16)netdev->dev_addr[0]) << 8;
+       macaddr_high  = ((u16)netdev->dev_addr[0]) << 8;
        macaddr_high += (u16)netdev->dev_addr[1];
-       macaddr_low = ((u32)netdev->dev_addr[2]) << 24;
-       macaddr_low += ((u32)netdev->dev_addr[3]) << 16;
-       macaddr_low += ((u32)netdev->dev_addr[4]) << 8;
-       macaddr_low += (u32)netdev->dev_addr[5];
+       macaddr_low   = ((u32)netdev->dev_addr[2]) << 24;
+       macaddr_low  += ((u32)netdev->dev_addr[3]) << 16;
+       macaddr_low  += ((u32)netdev->dev_addr[4]) << 8;
+       macaddr_low  += (u32)netdev->dev_addr[5];
 
        for (i = 0; i < NES_MAX_PORT_COUNT; i++) {
                if (nesvnic->qp_nic_index[i] == 0xf) {
@@ -881,12 +883,12 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev)
                                          print_mac(mac, multicast_addr->dmi_addr),
                                          perfect_filter_register_address+(mc_index * 8),
                                          mc_nic_index);
-                               macaddr_high = ((u16)multicast_addr->dmi_addr[0]) << 8;
+                               macaddr_high  = ((u16)multicast_addr->dmi_addr[0]) << 8;
                                macaddr_high += (u16)multicast_addr->dmi_addr[1];
-                               macaddr_low = ((u32)multicast_addr->dmi_addr[2]) << 24;
-                               macaddr_low += ((u32)multicast_addr->dmi_addr[3]) << 16;
-                               macaddr_low += ((u32)multicast_addr->dmi_addr[4]) << 8;
-                               macaddr_low += (u32)multicast_addr->dmi_addr[5];
+                               macaddr_low   = ((u32)multicast_addr->dmi_addr[2]) << 24;
+                               macaddr_low  += ((u32)multicast_addr->dmi_addr[3]) << 16;
+                               macaddr_low  += ((u32)multicast_addr->dmi_addr[4]) << 8;
+                               macaddr_low  += (u32)multicast_addr->dmi_addr[5];
                                nes_write_indexed(nesdev,
                                                perfect_filter_register_address+(mc_index * 8),
                                                macaddr_low);
@@ -910,23 +912,23 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev)
 /**
  * nes_netdev_change_mtu
  */
-static int nes_netdev_change_mtu(struct        net_device *netdev,     int     new_mtu)
+static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct nes_vnic *nesvnic = netdev_priv(netdev);
-       struct nes_device *nesdev =     nesvnic->nesdev;
-       int     ret     = 0;
-       u8 jumbomode=0;
+       struct nes_device *nesdev = nesvnic->nesdev;
+       int ret = 0;
+       u8 jumbomode = 0;
 
-       if ((new_mtu < ETH_ZLEN) ||     (new_mtu > max_mtu))
+       if ((new_mtu < ETH_ZLEN) || (new_mtu > max_mtu))
                return -EINVAL;
 
-       netdev->mtu     = new_mtu;
+       netdev->mtu = new_mtu;
        nesvnic->max_frame_size = new_mtu + VLAN_ETH_HLEN;
 
        if (netdev->mtu > 1500) {
                jumbomode=1;
        }
-       nes_nic_init_timer_defaults(nesdev,     jumbomode);
+       nes_nic_init_timer_defaults(nesdev, jumbomode);
 
        if (netif_running(netdev)) {
                nes_netdev_stop(netdev);
@@ -936,8 +938,7 @@ static int nes_netdev_change_mtu(struct     net_device *netdev,     int     new_mtu)
        return ret;
 }
 
-#define NES_ETHTOOL_STAT_COUNT 55
-static const char nes_ethtool_stringset[NES_ETHTOOL_STAT_COUNT][ETH_GSTRING_LEN] = {
+static const char nes_ethtool_stringset[][ETH_GSTRING_LEN] = {
        "Link Change Interrupts",
        "Linearized SKBs",
        "T/GSO Requests",
@@ -993,8 +994,12 @@ static const char nes_ethtool_stringset[NES_ETHTOOL_STAT_COUNT][ETH_GSTRING_LEN]
        "CQ Depth 32",
        "CQ Depth 128",
        "CQ Depth 256",
+       "LRO aggregated",
+       "LRO flushed",
+       "LRO no_desc",
 };
 
+#define NES_ETHTOOL_STAT_COUNT  ARRAY_SIZE(nes_ethtool_stringset)
 
 /**
  * nes_netdev_get_rx_csum
@@ -1189,6 +1194,9 @@ static void nes_netdev_get_ethtool_stats(struct net_device *netdev,
        target_stat_values[52] = int_mod_cq_depth_32;
        target_stat_values[53] = int_mod_cq_depth_128;
        target_stat_values[54] = int_mod_cq_depth_256;
+       target_stat_values[55] = nesvnic->lro_mgr.stats.aggregated;
+       target_stat_values[56] = nesvnic->lro_mgr.stats.flushed;
+       target_stat_values[57] = nesvnic->lro_mgr.stats.no_desc;
 
 }
 
@@ -1219,14 +1227,14 @@ static int nes_netdev_set_coalesce(struct net_device *netdev,
                struct ethtool_coalesce *et_coalesce)
 {
        struct nes_vnic *nesvnic = netdev_priv(netdev);
-       struct nes_device *nesdev =     nesvnic->nesdev;
+       struct nes_device *nesdev = nesvnic->nesdev;
        struct nes_adapter *nesadapter = nesdev->nesadapter;
        struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;
        unsigned long flags;
 
-       spin_lock_irqsave(&nesadapter->periodic_timer_lock,     flags);
+       spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);
        if (et_coalesce->rx_max_coalesced_frames_low) {
-               shared_timer->threshold_low      = et_coalesce->rx_max_coalesced_frames_low;
+               shared_timer->threshold_low = et_coalesce->rx_max_coalesced_frames_low;
        }
        if (et_coalesce->rx_max_coalesced_frames_irq) {
                shared_timer->threshold_target = et_coalesce->rx_max_coalesced_frames_irq;
@@ -1246,14 +1254,14 @@ static int nes_netdev_set_coalesce(struct net_device *netdev,
        nesadapter->et_rx_coalesce_usecs_irq = et_coalesce->rx_coalesce_usecs_irq;
        if (et_coalesce->use_adaptive_rx_coalesce) {
                nesadapter->et_use_adaptive_rx_coalesce = 1;
-               nesadapter->timer_int_limit     = NES_TIMER_INT_LIMIT_DYNAMIC;
+               nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT_DYNAMIC;
                nesadapter->et_rx_coalesce_usecs_irq = 0;
                if (et_coalesce->pkt_rate_low) {
-                       nesadapter->et_pkt_rate_low     = et_coalesce->pkt_rate_low;
+                       nesadapter->et_pkt_rate_low = et_coalesce->pkt_rate_low;
                }
        } else {
                nesadapter->et_use_adaptive_rx_coalesce = 0;
-               nesadapter->timer_int_limit     = NES_TIMER_INT_LIMIT;
+               nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT;
                if (nesadapter->et_rx_coalesce_usecs_irq) {
                        nes_write32(nesdev->regs+NES_PERIODIC_CONTROL,
                                        0x80000000 | ((u32)(nesadapter->et_rx_coalesce_usecs_irq*8)));
@@ -1270,28 +1278,28 @@ static int nes_netdev_get_coalesce(struct net_device *netdev,
                struct ethtool_coalesce *et_coalesce)
 {
        struct nes_vnic *nesvnic = netdev_priv(netdev);
-       struct nes_device *nesdev =     nesvnic->nesdev;
+       struct nes_device *nesdev = nesvnic->nesdev;
        struct nes_adapter *nesadapter = nesdev->nesadapter;
        struct ethtool_coalesce temp_et_coalesce;
        struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;
        unsigned long flags;
 
        memset(&temp_et_coalesce, 0, sizeof(temp_et_coalesce));
-       temp_et_coalesce.rx_coalesce_usecs_irq = nesadapter->et_rx_coalesce_usecs_irq;
-       temp_et_coalesce.use_adaptive_rx_coalesce =     nesadapter->et_use_adaptive_rx_coalesce;
-       temp_et_coalesce.rate_sample_interval = nesadapter->et_rate_sample_interval;
+       temp_et_coalesce.rx_coalesce_usecs_irq    = nesadapter->et_rx_coalesce_usecs_irq;
+       temp_et_coalesce.use_adaptive_rx_coalesce = nesadapter->et_use_adaptive_rx_coalesce;
+       temp_et_coalesce.rate_sample_interval     = nesadapter->et_rate_sample_interval;
        temp_et_coalesce.pkt_rate_low = nesadapter->et_pkt_rate_low;
        spin_lock_irqsave(&nesadapter->periodic_timer_lock,     flags);
-       temp_et_coalesce.rx_max_coalesced_frames_low  shared_timer->threshold_low;
-       temp_et_coalesce.rx_max_coalesced_frames_irq  shared_timer->threshold_target;
+       temp_et_coalesce.rx_max_coalesced_frames_low  = shared_timer->threshold_low;
+       temp_et_coalesce.rx_max_coalesced_frames_irq  = shared_timer->threshold_target;
        temp_et_coalesce.rx_max_coalesced_frames_high = shared_timer->threshold_high;
-       temp_et_coalesce.rx_coalesce_usecs_low = shared_timer->timer_in_use_min;
+       temp_et_coalesce.rx_coalesce_usecs_low  = shared_timer->timer_in_use_min;
        temp_et_coalesce.rx_coalesce_usecs_high = shared_timer->timer_in_use_max;
        if (nesadapter->et_use_adaptive_rx_coalesce) {
                temp_et_coalesce.rx_coalesce_usecs_irq = shared_timer->timer_in_use;
        }
        spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);
-       memcpy(et_coalesce,     &temp_et_coalesce, sizeof(*et_coalesce));
+       memcpy(et_coalesce, &temp_et_coalesce, sizeof(*et_coalesce));
        return 0;
 }
 
@@ -1370,30 +1378,38 @@ static int nes_netdev_get_settings(struct net_device *netdev, struct ethtool_cmd
        u16 phy_data;
 
        et_cmd->duplex = DUPLEX_FULL;
-       et_cmd->port = PORT_MII;
+       et_cmd->port   = PORT_MII;
+
        if (nesadapter->OneG_Mode) {
-               et_cmd->supported = SUPPORTED_1000baseT_Full|SUPPORTED_Autoneg;
-               et_cmd->advertising = ADVERTISED_1000baseT_Full|ADVERTISED_Autoneg;
                et_cmd->speed = SPEED_1000;
-               nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[nesdev->mac_index],
-                               &phy_data);
-               if (phy_data&0x1000) {
-                       et_cmd->autoneg = AUTONEG_ENABLE;
+               if (nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_PUMA_1G) {
+                       et_cmd->supported   = SUPPORTED_1000baseT_Full;
+                       et_cmd->advertising = ADVERTISED_1000baseT_Full;
+                       et_cmd->autoneg     = AUTONEG_DISABLE;
+                       et_cmd->transceiver = XCVR_INTERNAL;
+                       et_cmd->phy_address = nesdev->mac_index;
                } else {
-                       et_cmd->autoneg = AUTONEG_DISABLE;
+                       et_cmd->supported   = SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg;
+                       et_cmd->advertising = ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg;
+                       nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[nesdev->mac_index], &phy_data);
+                       if (phy_data & 0x1000)
+                               et_cmd->autoneg = AUTONEG_ENABLE;
+                       else
+                               et_cmd->autoneg = AUTONEG_DISABLE;
+                       et_cmd->transceiver = XCVR_EXTERNAL;
+                       et_cmd->phy_address = nesadapter->phy_index[nesdev->mac_index];
                }
-               et_cmd->transceiver = XCVR_EXTERNAL;
-               et_cmd->phy_address = nesadapter->phy_index[nesdev->mac_index];
        } else {
-               if (nesadapter->phy_type[nesvnic->logical_port] == NES_PHY_TYPE_IRIS) {
+               if ((nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_IRIS) ||
+                   (nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_ARGUS)) {
                        et_cmd->transceiver = XCVR_EXTERNAL;
-                       et_cmd->port = PORT_FIBRE;
-                       et_cmd->supported = SUPPORTED_FIBRE;
+                       et_cmd->port        = PORT_FIBRE;
+                       et_cmd->supported   = SUPPORTED_FIBRE;
                        et_cmd->advertising = ADVERTISED_FIBRE;
                        et_cmd->phy_address = nesadapter->phy_index[nesdev->mac_index];
                } else {
                        et_cmd->transceiver = XCVR_INTERNAL;
-                       et_cmd->supported = SUPPORTED_10000baseT_Full;
+                       et_cmd->supported   = SUPPORTED_10000baseT_Full;
                        et_cmd->advertising = ADVERTISED_10000baseT_Full;
                        et_cmd->phy_address = nesdev->mac_index;
                }
@@ -1416,14 +1432,15 @@ static int nes_netdev_set_settings(struct net_device *netdev, struct ethtool_cmd
        struct nes_adapter *nesadapter = nesdev->nesadapter;
        u16 phy_data;
 
-       if (nesadapter->OneG_Mode) {
+       if ((nesadapter->OneG_Mode) &&
+           (nesadapter->phy_type[nesdev->mac_index] != NES_PHY_TYPE_PUMA_1G)) {
                nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[nesdev->mac_index],
                                &phy_data);
                if (et_cmd->autoneg) {
                        /* Turn on Full duplex, Autoneg, and restart autonegotiation */
                        phy_data |= 0x1300;
                } else {
-                       // Turn off autoneg
+                       /* Turn off autoneg */
                        phy_data &= ~0x1000;
                }
                nes_write_1G_phy_reg(nesdev, 0, nesadapter->phy_index[nesdev->mac_index],
@@ -1454,6 +1471,8 @@ static struct ethtool_ops nes_ethtool_ops = {
        .set_sg = ethtool_op_set_sg,
        .get_tso = ethtool_op_get_tso,
        .set_tso = ethtool_op_set_tso,
+       .get_flags = ethtool_op_get_flags,
+       .set_flags = ethtool_op_set_flags,
 };
 
 
@@ -1607,27 +1626,34 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
        list_add_tail(&nesvnic->list, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]);
 
        if ((nesdev->netdev_count == 0) &&
-           (PCI_FUNC(nesdev->pcidev->devfn) == nesdev->mac_index)) {
-               nes_debug(NES_DBG_INIT, "Setting up PHY interrupt mask. Using register index 0x%04X\n",
-                               NES_IDX_PHY_PCS_CONTROL_STATUS0+(0x200*(nesvnic->logical_port&1)));
+           ((PCI_FUNC(nesdev->pcidev->devfn) == nesdev->mac_index) ||
+            ((nesdev->nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_PUMA_1G) &&
+             (((PCI_FUNC(nesdev->pcidev->devfn) == 1) && (nesdev->mac_index == 2)) ||
+              ((PCI_FUNC(nesdev->pcidev->devfn) == 2) && (nesdev->mac_index == 1)))))) {
+               /*
+                * nes_debug(NES_DBG_INIT, "Setting up PHY interrupt mask. Using register index 0x%04X\n",
+                *              NES_IDX_PHY_PCS_CONTROL_STATUS0 + (0x200 * (nesvnic->logical_port & 1)));
+                */
                u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
-                               (0x200*(nesvnic->logical_port&1)));
-               u32temp |= 0x00200000;
-               nes_write_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
-                               (0x200*(nesvnic->logical_port&1)), u32temp);
+                               (0x200 * (nesdev->mac_index & 1)));
+               if (nesdev->nesadapter->phy_type[nesdev->mac_index] != NES_PHY_TYPE_PUMA_1G) {
+                       u32temp |= 0x00200000;
+                       nes_write_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
+                               (0x200 * (nesdev->mac_index & 1)), u32temp);
+               }
+
                u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
-                               (0x200*(nesvnic->logical_port&1)) );
+                               (0x200 * (nesdev->mac_index & 1)));
+
                if ((u32temp&0x0f1f0000) == 0x0f0f0000) {
-                       if (nesdev->nesadapter->phy_type[nesvnic->logical_port] == NES_PHY_TYPE_IRIS) {
+                       if (nesdev->nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_IRIS) {
                                nes_init_phy(nesdev);
-                               nes_read_10G_phy_reg(nesdev, 1,
-                                               nesdev->nesadapter->phy_index[nesvnic->logical_port]);
+                               nes_read_10G_phy_reg(nesdev, nesdev->nesadapter->phy_index[nesdev->mac_index], 1, 1);
                                temp_phy_data = (u16)nes_read_indexed(nesdev,
                                                                        NES_IDX_MAC_MDIO_CONTROL);
                                u32temp = 20;
                                do {
-                                       nes_read_10G_phy_reg(nesdev, 1,
-                                                       nesdev->nesadapter->phy_index[nesvnic->logical_port]);
+                                       nes_read_10G_phy_reg(nesdev, nesdev->nesadapter->phy_index[nesdev->mac_index], 1, 1);
                                        phy_data = (u16)nes_read_indexed(nesdev,
                                                                        NES_IDX_MAC_MDIO_CONTROL);
                                        if ((phy_data == temp_phy_data) || (!(--u32temp)))
@@ -1644,6 +1670,14 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
                                nes_debug(NES_DBG_INIT, "The Link is UP!!.\n");
                                nesvnic->linkup = 1;
                        }
+               } else if (nesdev->nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_PUMA_1G) {
+                       nes_debug(NES_DBG_INIT, "mac_index=%d, logical_port=%d, u32temp=0x%04X, PCI_FUNC=%d\n",
+                               nesdev->mac_index, nesvnic->logical_port, u32temp, PCI_FUNC(nesdev->pcidev->devfn));
+                       if (((nesdev->mac_index < 2) && ((u32temp&0x01010000) == 0x01010000)) ||
+                           ((nesdev->mac_index > 1) && ((u32temp&0x02020000) == 0x02020000)))  {
+                               nes_debug(NES_DBG_INIT, "The Link is UP!!.\n");
+                               nesvnic->linkup = 1;
+                       }
                }
                /* clear the MAC interrupt status, assumes direct logical to physical mapping */
                u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index));
index c6d5631a699546ddee342b255965b01c72c7c434..fe83d1b2b177161a395ed826a7521181834ab8c2 100644 (file)
@@ -444,15 +444,13 @@ void nes_read_1G_phy_reg(struct nes_device *nesdev, u8 phy_reg, u8 phy_addr, u16
 /**
  * nes_write_10G_phy_reg
  */
-void nes_write_10G_phy_reg(struct nes_device *nesdev, u16 phy_reg,
-               u8 phy_addr, u16 data)
+void nes_write_10G_phy_reg(struct nes_device *nesdev, u16 phy_addr, u8 dev_addr, u16 phy_reg,
+               u16 data)
 {
-       u32 dev_addr;
        u32 port_addr;
        u32 u32temp;
        u32 counter;
 
-       dev_addr = 1;
        port_addr = phy_addr;
 
        /* set address */
@@ -492,14 +490,12 @@ void nes_write_10G_phy_reg(struct nes_device *nesdev, u16 phy_reg,
  * This routine only issues the read, the data must be read
  * separately.
  */
-void nes_read_10G_phy_reg(struct nes_device *nesdev, u16 phy_reg, u8 phy_addr)
+void nes_read_10G_phy_reg(struct nes_device *nesdev, u8 phy_addr, u8 dev_addr, u16 phy_reg)
 {
-       u32 dev_addr;
        u32 port_addr;
        u32 u32temp;
        u32 counter;
 
-       dev_addr = 1;
        port_addr = phy_addr;
 
        /* set address */
index ee74f7c7a6da85b3b163f0f1a5ab9171691705a5..99b3c4ae86eb0e1c71e0d03c4ebdde85b098155a 100644 (file)
@@ -1266,7 +1266,7 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd,
                        sq_size = init_attr->cap.max_send_wr;
                        rq_size = init_attr->cap.max_recv_wr;
 
-                       // check if the encoded sizes are OK or not...
+                       /* check if the encoded sizes are OK or not... */
                        sq_encoded_size = nes_get_encoded_size(&sq_size);
                        rq_encoded_size = nes_get_encoded_size(&rq_size);
 
@@ -2377,7 +2377,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
        u8 single_page = 1;
        u8 stag_key;
 
-       region = ib_umem_get(pd->uobject->context, start, length, acc);
+       region = ib_umem_get(pd->uobject->context, start, length, acc, 0);
        if (IS_ERR(region)) {
                return (struct ib_mr *)region;
        }
index f1f142dc64b17e8608f0f668345a13af3b65fb65..9044f8803532e035e264e2b166644b05d84563e4 100644 (file)
@@ -95,6 +95,8 @@ enum {
        IPOIB_MCAST_FLAG_SENDONLY = 1,
        IPOIB_MCAST_FLAG_BUSY     = 2,  /* joining or already joined */
        IPOIB_MCAST_FLAG_ATTACHED = 3,
+
+       MAX_SEND_CQE              = 16,
 };
 
 #define        IPOIB_OP_RECV   (1ul << 31)
@@ -285,7 +287,8 @@ struct ipoib_dev_priv {
        u16               pkey_index;
        struct ib_pd     *pd;
        struct ib_mr     *mr;
-       struct ib_cq     *cq;
+       struct ib_cq     *recv_cq;
+       struct ib_cq     *send_cq;
        struct ib_qp     *qp;
        u32               qkey;
 
@@ -305,6 +308,7 @@ struct ipoib_dev_priv {
        struct ib_sge        tx_sge[MAX_SKB_FRAGS + 1];
        struct ib_send_wr    tx_wr;
        unsigned             tx_outstanding;
+       struct ib_wc         send_wc[MAX_SEND_CQE];
 
        struct ib_recv_wr    rx_wr;
        struct ib_sge        rx_sge[IPOIB_UD_RX_SG];
@@ -662,7 +666,6 @@ static inline int ipoib_register_debugfs(void) { return 0; }
 static inline void ipoib_unregister_debugfs(void) { }
 #endif
 
-
 #define ipoib_printk(level, priv, format, arg...)      \
        printk(level "%s: " format, ((struct ipoib_dev_priv *) priv)->dev->name , ## arg)
 #define ipoib_warn(priv, format, arg...)               \
index 9db7b0bd9134b350befa605a40b122081fe861a4..97e67d36378fa1532cb2224624ae20ea53acefe2 100644 (file)
@@ -249,8 +249,8 @@ static struct ib_qp *ipoib_cm_create_rx_qp(struct net_device *dev,
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct ib_qp_init_attr attr = {
                .event_handler = ipoib_cm_rx_event_handler,
-               .send_cq = priv->cq, /* For drain WR */
-               .recv_cq = priv->cq,
+               .send_cq = priv->recv_cq, /* For drain WR */
+               .recv_cq = priv->recv_cq,
                .srq = priv->cm.srq,
                .cap.max_send_wr = 1, /* For drain WR */
                .cap.max_send_sge = 1, /* FIXME: 0 Seems not to work */
@@ -951,8 +951,8 @@ static struct ib_qp *ipoib_cm_create_tx_qp(struct net_device *dev, struct ipoib_
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct ib_qp_init_attr attr = {
-               .send_cq                = priv->cq,
-               .recv_cq                = priv->cq,
+               .send_cq                = priv->recv_cq,
+               .recv_cq                = priv->recv_cq,
                .srq                    = priv->cm.srq,
                .cap.max_send_wr        = ipoib_sendq_size,
                .cap.max_send_sge       = 1,
index 9a47428366c91d0f35884ff2cecb0bbf49c41846..10279b79c44d92b9f2384f653fcf9204cf77159d 100644 (file)
@@ -71,7 +71,7 @@ static int ipoib_set_coalesce(struct net_device *dev,
            coal->rx_max_coalesced_frames > 0xffff)
                return -EINVAL;
 
-       ret = ib_modify_cq(priv->cq, coal->rx_max_coalesced_frames,
+       ret = ib_modify_cq(priv->recv_cq, coal->rx_max_coalesced_frames,
                           coal->rx_coalesce_usecs);
        if (ret && ret != -ENOSYS) {
                ipoib_warn(priv, "failed modifying CQ (%d)\n", ret);
index 7cf1fa7074abfa28ca31e298c8c2c04a53b75ab8..97b815c1a3fc0988a33129e47ace54748d9d9dbb 100644 (file)
@@ -364,7 +364,6 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        unsigned int wr_id = wc->wr_id;
        struct ipoib_tx_buf *tx_req;
-       unsigned long flags;
 
        ipoib_dbg_data(priv, "send completion: id %d, status: %d\n",
                       wr_id, wc->status);
@@ -384,13 +383,11 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
 
        dev_kfree_skb_any(tx_req->skb);
 
-       spin_lock_irqsave(&priv->tx_lock, flags);
        ++priv->tx_tail;
        if (unlikely(--priv->tx_outstanding == ipoib_sendq_size >> 1) &&
            netif_queue_stopped(dev) &&
            test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
                netif_wake_queue(dev);
-       spin_unlock_irqrestore(&priv->tx_lock, flags);
 
        if (wc->status != IB_WC_SUCCESS &&
            wc->status != IB_WC_WR_FLUSH_ERR)
@@ -399,6 +396,17 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
                           wc->status, wr_id, wc->vendor_err);
 }
 
+static int poll_tx(struct ipoib_dev_priv *priv)
+{
+       int n, i;
+
+       n = ib_poll_cq(priv->send_cq, MAX_SEND_CQE, priv->send_wc);
+       for (i = 0; i < n; ++i)
+               ipoib_ib_handle_tx_wc(priv->dev, priv->send_wc + i);
+
+       return n == MAX_SEND_CQE;
+}
+
 int ipoib_poll(struct napi_struct *napi, int budget)
 {
        struct ipoib_dev_priv *priv = container_of(napi, struct ipoib_dev_priv, napi);
@@ -414,7 +422,7 @@ poll_more:
                int max = (budget - done);
 
                t = min(IPOIB_NUM_WC, max);
-               n = ib_poll_cq(priv->cq, t, priv->ibwc);
+               n = ib_poll_cq(priv->recv_cq, t, priv->ibwc);
 
                for (i = 0; i < n; i++) {
                        struct ib_wc *wc = priv->ibwc + i;
@@ -425,12 +433,8 @@ poll_more:
                                        ipoib_cm_handle_rx_wc(dev, wc);
                                else
                                        ipoib_ib_handle_rx_wc(dev, wc);
-                       } else {
-                               if (wc->wr_id & IPOIB_OP_CM)
-                                       ipoib_cm_handle_tx_wc(dev, wc);
-                               else
-                                       ipoib_ib_handle_tx_wc(dev, wc);
-                       }
+                       } else
+                               ipoib_cm_handle_tx_wc(priv->dev, wc);
                }
 
                if (n != t)
@@ -439,7 +443,7 @@ poll_more:
 
        if (done < budget) {
                netif_rx_complete(dev, napi);
-               if (unlikely(ib_req_notify_cq(priv->cq,
+               if (unlikely(ib_req_notify_cq(priv->recv_cq,
                                              IB_CQ_NEXT_COMP |
                                              IB_CQ_REPORT_MISSED_EVENTS)) &&
                    netif_rx_reschedule(dev, napi))
@@ -562,12 +566,16 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
 
                address->last_send = priv->tx_head;
                ++priv->tx_head;
+               skb_orphan(skb);
 
                if (++priv->tx_outstanding == ipoib_sendq_size) {
                        ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n");
                        netif_stop_queue(dev);
                }
        }
+
+       if (unlikely(priv->tx_outstanding > MAX_SEND_CQE))
+               poll_tx(priv);
 }
 
 static void __ipoib_reap_ah(struct net_device *dev)
@@ -714,7 +722,7 @@ void ipoib_drain_cq(struct net_device *dev)
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        int i, n;
        do {
-               n = ib_poll_cq(priv->cq, IPOIB_NUM_WC, priv->ibwc);
+               n = ib_poll_cq(priv->recv_cq, IPOIB_NUM_WC, priv->ibwc);
                for (i = 0; i < n; ++i) {
                        /*
                         * Convert any successful completions to flush
@@ -729,14 +737,13 @@ void ipoib_drain_cq(struct net_device *dev)
                                        ipoib_cm_handle_rx_wc(dev, priv->ibwc + i);
                                else
                                        ipoib_ib_handle_rx_wc(dev, priv->ibwc + i);
-                       } else {
-                               if (priv->ibwc[i].wr_id & IPOIB_OP_CM)
-                                       ipoib_cm_handle_tx_wc(dev, priv->ibwc + i);
-                               else
-                                       ipoib_ib_handle_tx_wc(dev, priv->ibwc + i);
-                       }
+                       } else
+                               ipoib_cm_handle_tx_wc(dev, priv->ibwc + i);
                }
        } while (n == IPOIB_NUM_WC);
+
+       while (poll_tx(priv))
+               ; /* nothing */
 }
 
 int ipoib_ib_dev_stop(struct net_device *dev, int flush)
@@ -826,7 +833,7 @@ timeout:
                msleep(1);
        }
 
-       ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP);
+       ib_req_notify_cq(priv->recv_cq, IB_CQ_NEXT_COMP);
 
        return 0;
 }
index 7a4ed9d3d8447368466aad077abea153c5b776c0..2442090ac8d1dbfe083bfca69d46adc2b484c157 100644 (file)
@@ -1298,7 +1298,8 @@ static int __init ipoib_init_module(void)
 
        ipoib_sendq_size = roundup_pow_of_two(ipoib_sendq_size);
        ipoib_sendq_size = min(ipoib_sendq_size, IPOIB_MAX_QUEUE_SIZE);
-       ipoib_sendq_size = max(ipoib_sendq_size, IPOIB_MIN_QUEUE_SIZE);
+       ipoib_sendq_size = max(ipoib_sendq_size, max(2 * MAX_SEND_CQE,
+                                                    IPOIB_MIN_QUEUE_SIZE));
 #ifdef CONFIG_INFINIBAND_IPOIB_CM
        ipoib_max_conn_qp = min(ipoib_max_conn_qp, IPOIB_CM_MAX_CONN_QP);
 #endif
index 07c03f178a498b0ff6488a32a1cfe45057864c5b..c1e7ece1fd440ffd61efc2260ade377cc87df47e 100644 (file)
@@ -171,26 +171,33 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
                goto out_free_pd;
        }
 
-       size = ipoib_sendq_size + ipoib_recvq_size + 1;
+       size = ipoib_recvq_size + 1;
        ret = ipoib_cm_dev_init(dev);
        if (!ret) {
+               size += ipoib_sendq_size;
                if (ipoib_cm_has_srq(dev))
                        size += ipoib_recvq_size + 1; /* 1 extra for rx_drain_qp */
                else
                        size += ipoib_recvq_size * ipoib_max_conn_qp;
        }
 
-       priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size, 0);
-       if (IS_ERR(priv->cq)) {
-               printk(KERN_WARNING "%s: failed to create CQ\n", ca->name);
+       priv->recv_cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size, 0);
+       if (IS_ERR(priv->recv_cq)) {
+               printk(KERN_WARNING "%s: failed to create receive CQ\n", ca->name);
                goto out_free_mr;
        }
 
-       if (ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP))
-               goto out_free_cq;
+       priv->send_cq = ib_create_cq(priv->ca, NULL, NULL, dev, ipoib_sendq_size, 0);
+       if (IS_ERR(priv->send_cq)) {
+               printk(KERN_WARNING "%s: failed to create send CQ\n", ca->name);
+               goto out_free_recv_cq;
+       }
+
+       if (ib_req_notify_cq(priv->recv_cq, IB_CQ_NEXT_COMP))
+               goto out_free_send_cq;
 
-       init_attr.send_cq = priv->cq;
-       init_attr.recv_cq = priv->cq;
+       init_attr.send_cq = priv->send_cq;
+       init_attr.recv_cq = priv->recv_cq;
 
        if (priv->hca_caps & IB_DEVICE_UD_TSO)
                init_attr.create_flags = IB_QP_CREATE_IPOIB_UD_LSO;
@@ -201,7 +208,7 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
        priv->qp = ib_create_qp(priv->pd, &init_attr);
        if (IS_ERR(priv->qp)) {
                printk(KERN_WARNING "%s: failed to create QP\n", ca->name);
-               goto out_free_cq;
+               goto out_free_send_cq;
        }
 
        priv->dev->dev_addr[1] = (priv->qp->qp_num >> 16) & 0xff;
@@ -230,8 +237,11 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
 
        return 0;
 
-out_free_cq:
-       ib_destroy_cq(priv->cq);
+out_free_send_cq:
+       ib_destroy_cq(priv->send_cq);
+
+out_free_recv_cq:
+       ib_destroy_cq(priv->recv_cq);
 
 out_free_mr:
        ib_dereg_mr(priv->mr);
@@ -254,8 +264,11 @@ void ipoib_transport_dev_cleanup(struct net_device *dev)
                clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
        }
 
-       if (ib_destroy_cq(priv->cq))
-               ipoib_warn(priv, "ib_cq_destroy failed\n");
+       if (ib_destroy_cq(priv->send_cq))
+               ipoib_warn(priv, "ib_cq_destroy (send) failed\n");
+
+       if (ib_destroy_cq(priv->recv_cq))
+               ipoib_warn(priv, "ib_cq_destroy (recv) failed\n");
 
        ipoib_cm_dev_cleanup(dev);
 
index 431fdeaa2dc4f8075fd9ecb5c7b0b41382dcd207..1cdb5cfb0ff12f3cce46c149650cdd3e53f4bb87 100644 (file)
@@ -90,6 +90,9 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
        }
 
        priv->max_ib_mtu = ppriv->max_ib_mtu;
+       /* MTU will be reset when mcast join happens */
+       priv->dev->mtu   = IPOIB_UD_MTU(priv->max_ib_mtu);
+       priv->mcast_mtu  = priv->admin_mtu = priv->dev->mtu;
        set_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags);
 
        priv->pkey = pkey;
index be1b9fbd416d9cf2a2c70dad4542278704448058..aeb58cae9a3fa4ca8aaec0a949f2cb72f4815aa9 100644 (file)
@@ -473,13 +473,15 @@ iscsi_iser_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *s
        stats->r2t_pdus = conn->r2t_pdus_cnt; /* always 0 */
        stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
        stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
-       stats->custom_length = 3;
+       stats->custom_length = 4;
        strcpy(stats->custom[0].desc, "qp_tx_queue_full");
        stats->custom[0].value = 0; /* TB iser_conn->qp_tx_queue_full; */
        strcpy(stats->custom[1].desc, "fmr_map_not_avail");
        stats->custom[1].value = 0; /* TB iser_conn->fmr_map_not_avail */;
        strcpy(stats->custom[2].desc, "eh_abort_cnt");
        stats->custom[2].value = conn->eh_abort_cnt;
+       strcpy(stats->custom[3].desc, "fmr_unalign_cnt");
+       stats->custom[3].value = conn->fmr_unalign_cnt;
 }
 
 static int
index 1ee867b1b3411754c58a814331283944b45b9587..a8c1b300e34d54d76eb18eeb646db24b2c34b598 100644 (file)
 #define DRV_DATE       "May 7th, 2006"
 
 #define iser_dbg(fmt, arg...)                          \
+       do {                                            \
+               if (iser_debug_level > 1)               \
+                       printk(KERN_DEBUG PFX "%s:" fmt,\
+                               __func__ , ## arg);     \
+       } while (0)
+
+#define iser_warn(fmt, arg...)                         \
        do {                                            \
                if (iser_debug_level > 0)               \
                        printk(KERN_DEBUG PFX "%s:" fmt,\
index 4a17743a639f2ae884f4cbe122e8e68f1a6f12b9..cac50c4dc159df8c1202640d6bc0ab13e6b8cc22 100644 (file)
@@ -334,8 +334,11 @@ static void iser_data_buf_dump(struct iser_data_buf *data,
        struct scatterlist *sg;
        int i;
 
+       if (iser_debug_level == 0)
+               return;
+
        for_each_sg(sgl, sg, data->dma_nents, i)
-               iser_err("sg[%d] dma_addr:0x%lX page:0x%p "
+               iser_warn("sg[%d] dma_addr:0x%lX page:0x%p "
                         "off:0x%x sz:0x%x dma_len:0x%x\n",
                         i, (unsigned long)ib_sg_dma_address(ibdev, sg),
                         sg_page(sg), sg->offset,
@@ -420,6 +423,7 @@ void iser_dma_unmap_task_data(struct iscsi_iser_cmd_task *iser_ctask)
 int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask,
                      enum   iser_data_dir        cmd_dir)
 {
+       struct iscsi_conn    *iscsi_conn = iser_ctask->iser_conn->iscsi_conn;
        struct iser_conn     *ib_conn = iser_ctask->iser_conn->ib_conn;
        struct iser_device   *device = ib_conn->device;
        struct ib_device     *ibdev = device->ib_device;
@@ -434,7 +438,8 @@ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask,
 
        aligned_len = iser_data_buf_aligned_len(mem, ibdev);
        if (aligned_len != mem->dma_nents) {
-               iser_err("rdma alignment violation %d/%d aligned\n",
+               iscsi_conn->fmr_unalign_cnt++;
+               iser_warn("rdma alignment violation %d/%d aligned\n",
                         aligned_len, mem->size);
                iser_data_buf_dump(mem, ibdev);
 
index f02c242c31145483c0b1836101d0aa27d402c7b2..27006fc1830567f30c87bc16a323cd826bd0ab46 100644 (file)
@@ -898,30 +898,26 @@ static int __init input_proc_init(void)
 {
        struct proc_dir_entry *entry;
 
-       proc_bus_input_dir = proc_mkdir("input", proc_bus);
+       proc_bus_input_dir = proc_mkdir("bus/input", NULL);
        if (!proc_bus_input_dir)
                return -ENOMEM;
 
        proc_bus_input_dir->owner = THIS_MODULE;
 
-       entry = create_proc_entry("devices", 0, proc_bus_input_dir);
+       entry = proc_create("devices", 0, proc_bus_input_dir,
+                           &input_devices_fileops);
        if (!entry)
                goto fail1;
 
-       entry->owner = THIS_MODULE;
-       entry->proc_fops = &input_devices_fileops;
-
-       entry = create_proc_entry("handlers", 0, proc_bus_input_dir);
+       entry = proc_create("handlers", 0, proc_bus_input_dir,
+                           &input_handlers_fileops);
        if (!entry)
                goto fail2;
 
-       entry->owner = THIS_MODULE;
-       entry->proc_fops = &input_handlers_fileops;
-
        return 0;
 
  fail2:        remove_proc_entry("devices", proc_bus_input_dir);
- fail1: remove_proc_entry("input", proc_bus);
+ fail1: remove_proc_entry("bus/input", NULL);
        return -ENOMEM;
 }
 
@@ -929,7 +925,7 @@ static void input_proc_exit(void)
 {
        remove_proc_entry("devices", proc_bus_input_dir);
        remove_proc_entry("handlers", proc_bus_input_dir);
-       remove_proc_entry("input", proc_bus);
+       remove_proc_entry("bus/input", NULL);
 }
 
 #else /* !CONFIG_PROC_FS */
index e1a3a79ab3f90ca309e92c9cc2bd2565b6c06211..7ff71ba7b7c90265875ed79052c18966a81a0614 100644 (file)
@@ -46,7 +46,7 @@ struct serport {
 static int serport_serio_write(struct serio *serio, unsigned char data)
 {
        struct serport *serport = serio->port_data;
-       return -(serport->tty->driver->write(serport->tty, &data, 1) != 1);
+       return -(serport->tty->ops->write(serport->tty, &data, 1) != 1);
 }
 
 static int serport_serio_open(struct serio *serio)
index 1d759f6f807670479171b21bdc20da2d17a46072..55c1134d61372aaf2889bb93f6cc33aef8b656ee 100644 (file)
@@ -528,9 +528,9 @@ static void aiptek_irq(struct urb *urb)
                            (aiptek->curSetting.pointerMode)) {
                                aiptek->diagnostic = AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED;
                } else {
-                       x = le16_to_cpu(get_unaligned((__le16 *) (data + 1)));
-                       y = le16_to_cpu(get_unaligned((__le16 *) (data + 3)));
-                       z = le16_to_cpu(get_unaligned((__le16 *) (data + 6)));
+                       x = get_unaligned_le16(data + 1);
+                       y = get_unaligned_le16(data + 3);
+                       z = get_unaligned_le16(data + 6);
 
                        dv = (data[5] & 0x01) != 0 ? 1 : 0;
                        p = (data[5] & 0x02) != 0 ? 1 : 0;
@@ -613,8 +613,8 @@ static void aiptek_irq(struct urb *urb)
                        (aiptek->curSetting.pointerMode)) {
                        aiptek->diagnostic = AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED;
                } else {
-                       x = le16_to_cpu(get_unaligned((__le16 *) (data + 1)));
-                       y = le16_to_cpu(get_unaligned((__le16 *) (data + 3)));
+                       x = get_unaligned_le16(data + 1);
+                       y = get_unaligned_le16(data + 3);
 
                        jitterable = data[5] & 0x1c;
 
@@ -679,7 +679,7 @@ static void aiptek_irq(struct urb *urb)
                pck = (data[1] & aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0;
 
                macro = dv && p && tip && !(data[3] & 1) ? (data[3] >> 1) : -1;
-               z = le16_to_cpu(get_unaligned((__le16 *) (data + 4)));
+               z = get_unaligned_le16(data + 4);
 
                if (dv) {
                        /* If the selected tool changed, reset the old
@@ -757,7 +757,7 @@ static void aiptek_irq(struct urb *urb)
         * hat switches (which just so happen to be the macroKeys.)
         */
        else if (data[0] == 6) {
-               macro = le16_to_cpu(get_unaligned((__le16 *) (data + 1)));
+               macro = get_unaligned_le16(data + 1);
                if (macro > 0) {
                        input_report_key(inputdev, macroKeyEvents[macro - 1],
                                         0);
@@ -952,7 +952,7 @@ aiptek_query(struct aiptek *aiptek, unsigned char command, unsigned char data)
                    buf[0], buf[1], buf[2]);
                ret = -EIO;
        } else {
-               ret = le16_to_cpu(get_unaligned((__le16 *) (buf + 1)));
+               ret = get_unaligned_le16(buf + 1);
        }
        kfree(buf);
        return ret;
index f66ca215cdec575ee46bff5c0d92b26957a19f7e..c5a8661a1baae242720bdd2c9f0eee248019c1d3 100644 (file)
@@ -245,11 +245,11 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
                        data = report[i];
                        break;
                case 2:
-                       data16 = le16_to_cpu(get_unaligned((__le16 *)&report[i]));
+                       data16 = get_unaligned_le16(&report[i]);
                        break;
                case 3:
                        size = 4;
-                       data32 = le32_to_cpu(get_unaligned((__le32 *)&report[i]));
+                       data32 = get_unaligned_le32(&report[i]);
                        break;
                }
 
@@ -695,10 +695,10 @@ static void gtco_urb_callback(struct urb *urbinfo)
                        /*  Fall thru */
                case 1:
                        /* All reports have X and Y coords in the same place */
-                       val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[1]));
+                       val = get_unaligned_le16(&device->buffer[1]);
                        input_report_abs(inputdev, ABS_X, val);
 
-                       val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[3]));
+                       val = get_unaligned_le16(&device->buffer[3]);
                        input_report_abs(inputdev, ABS_Y, val);
 
                        /* Ditto for proximity bit */
@@ -762,7 +762,7 @@ static void gtco_urb_callback(struct urb *urbinfo)
                                le_buffer[1]  = (u8)(device->buffer[4] >> 1);
                                le_buffer[1] |= (u8)((device->buffer[5] & 0x1) << 7);
 
-                               val = le16_to_cpu(get_unaligned((__le16 *)le_buffer));
+                               val = get_unaligned_le16(le_buffer);
                                input_report_abs(inputdev, ABS_Y, val);
 
                                /*
@@ -772,10 +772,10 @@ static void gtco_urb_callback(struct urb *urbinfo)
                                buttonbyte = device->buffer[5] >> 1;
                        } else {
 
-                               val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[1]));
+                               val = get_unaligned_le16(&device->buffer[1]);
                                input_report_abs(inputdev, ABS_X, val);
 
-                               val = le16_to_cpu(get_unaligned((__le16 *)&device->buffer[3]));
+                               val = get_unaligned_le16(&device->buffer[3]);
                                input_report_abs(inputdev, ABS_Y, val);
 
                                buttonbyte = device->buffer[5];
index 1182fc133167ac203e2d5e52cc71201ce4108c24..f23f5a97fb3868e58f5f23c730d38fb5c4eabc8d 100644 (file)
@@ -63,8 +63,8 @@ static void kbtab_irq(struct urb *urb)
                goto exit;
        }
 
-       kbtab->x = le16_to_cpu(get_unaligned((__le16 *) &data[1]));
-       kbtab->y = le16_to_cpu(get_unaligned((__le16 *) &data[3]));
+       kbtab->x = get_unaligned_le16(&data[1]);
+       kbtab->y = get_unaligned_le16(&data[3]);
 
        kbtab->pressure = (data[5]);
 
index 24c6b7ca62be46d2b583bb3565deae5982df6c26..6ca0bb949ad301a0ba109a73b342a1cb7833075f 100644 (file)
@@ -1111,11 +1111,12 @@ static int capinc_tty_write(struct tty_struct * tty,
        return count;
 }
 
-static void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
+static int capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
 {
        struct capiminor *mp = (struct capiminor *)tty->driver_data;
        struct sk_buff *skb;
        unsigned long flags;
+       int ret = 1;
 
 #ifdef _DEBUG_TTYFUNCS
        printk(KERN_DEBUG "capinc_put_char(%u)\n", ch);
@@ -1125,7 +1126,7 @@ static void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
 #ifdef _DEBUG_TTYFUNCS
                printk(KERN_DEBUG "capinc_tty_put_char: mp or mp->ncci NULL\n");
 #endif
-               return;
+               return 0;
        }
 
        spin_lock_irqsave(&workaround_lock, flags);
@@ -1134,7 +1135,7 @@ static void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
                if (skb_tailroom(skb) > 0) {
                        *(skb_put(skb, 1)) = ch;
                        spin_unlock_irqrestore(&workaround_lock, flags);
-                       return;
+                       return 1;
                }
                mp->ttyskb = NULL;
                skb_queue_tail(&mp->outqueue, skb);
@@ -1148,8 +1149,10 @@ static void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
                mp->ttyskb = skb;
        } else {
                printk(KERN_ERR "capinc_put_char: char %u lost\n", ch);
+               ret = 0;
        }
        spin_unlock_irqrestore(&workaround_lock, flags);
+       return ret;
 }
 
 static void capinc_tty_flush_chars(struct tty_struct *tty)
index 845a797b00309e2fb45fb1ce3f9defd5ed943146..c29208bd752131e9d8406c193a48f2a5982df272 100644 (file)
@@ -114,6 +114,7 @@ static int seq_contrstats_open(struct inode *inode, struct file *file)
 }
 
 static const struct file_operations proc_controller_ops = {
+       .owner          = THIS_MODULE,
        .open           = seq_controller_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -121,6 +122,7 @@ static const struct file_operations proc_controller_ops = {
 };
 
 static const struct file_operations proc_contrstats_ops = {
+       .owner          = THIS_MODULE,
        .open           = seq_contrstats_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -219,6 +221,7 @@ seq_applstats_open(struct inode *inode, struct file *file)
 }
 
 static const struct file_operations proc_applications_ops = {
+       .owner          = THIS_MODULE,
        .open           = seq_applications_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -226,21 +229,13 @@ static const struct file_operations proc_applications_ops = {
 };
 
 static const struct file_operations proc_applstats_ops = {
+       .owner          = THIS_MODULE,
        .open           = seq_applstats_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
        .release        = seq_release,
 };
 
-static void
-create_seq_entry(char *name, mode_t mode, const struct file_operations *f)
-{
-       struct proc_dir_entry *entry;
-       entry = create_proc_entry(name, mode, NULL);
-       if (entry)
-               entry->proc_fops = f;
-}
-
 // ---------------------------------------------------------------------------
 
 static void *capi_driver_start(struct seq_file *seq, loff_t *pos)
@@ -283,6 +278,7 @@ seq_capi_driver_open(struct inode *inode, struct file *file)
 }
 
 static const struct file_operations proc_driver_ops = {
+       .owner          = THIS_MODULE,
        .open           = seq_capi_driver_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -296,11 +292,11 @@ kcapi_proc_init(void)
 {
        proc_mkdir("capi",             NULL);
        proc_mkdir("capi/controllers", NULL);
-       create_seq_entry("capi/controller",   0, &proc_controller_ops);
-       create_seq_entry("capi/contrstats",   0, &proc_contrstats_ops);
-       create_seq_entry("capi/applications", 0, &proc_applications_ops);
-       create_seq_entry("capi/applstats",    0, &proc_applstats_ops);
-       create_seq_entry("capi/driver",       0, &proc_driver_ops);
+       proc_create("capi/controller",   0, NULL, &proc_controller_ops);
+       proc_create("capi/contrstats",   0, NULL, &proc_contrstats_ops);
+       proc_create("capi/applications", 0, NULL, &proc_applications_ops);
+       proc_create("capi/applstats",    0, NULL, &proc_applstats_ops);
+       proc_create("capi/driver",       0, NULL, &proc_driver_ops);
 }
 
 void __exit
index 4fd4c46892e3306ef3a18e181a4dc6e0735f4a9a..8b256a617c8a4524cec9f503ef7371ebbf30356b 100644 (file)
@@ -288,13 +288,12 @@ divert_dev_init(void)
        isdn_proc_entry = proc_mkdir("isdn", init_net.proc_net);
        if (!isdn_proc_entry)
                return (-1);
-       isdn_divert_entry = create_proc_entry("divert", S_IFREG | S_IRUGO, isdn_proc_entry);
+       isdn_divert_entry = proc_create("divert", S_IFREG | S_IRUGO,
+                                       isdn_proc_entry, &isdn_fops);
        if (!isdn_divert_entry) {
                remove_proc_entry("isdn", init_net.proc_net);
                return (-1);
        }
-       isdn_divert_entry->proc_fops = &isdn_fops; 
-       isdn_divert_entry->owner = THIS_MODULE; 
 #endif /* CONFIG_PROC_FS */
 
        return (0);
index fceeb1d57682849b3e438e63a265d4fd036efe78..45d1ee93cd39979e0f6788f73f9b7a4571eed4e6 100644 (file)
@@ -68,10 +68,10 @@ static int write_modem(struct cardstate *cs)
        struct tty_struct *tty = cs->hw.ser->tty;
        struct bc_state *bcs = &cs->bcs[0];     /* only one channel */
        struct sk_buff *skb = bcs->tx_skb;
-       int sent;
+       int sent = -EOPNOTSUPP;
 
        if (!tty || !tty->driver || !skb)
-               return -EFAULT;
+               return -EINVAL;
 
        if (!skb->len) {
                dev_kfree_skb_any(skb);
@@ -80,7 +80,8 @@ static int write_modem(struct cardstate *cs)
        }
 
        set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
-       sent = tty->driver->write(tty, skb->data, skb->len);
+       if (tty->ops->write)
+               sent = tty->ops->write(tty, skb->data, skb->len);
        gig_dbg(DEBUG_OUTPUT, "write_modem: sent %d", sent);
        if (sent < 0) {
                /* error */
@@ -120,7 +121,7 @@ static int send_cb(struct cardstate *cs)
 
        if (cb->len) {
                set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
-               sent = tty->driver->write(tty, cb->buf + cb->offset, cb->len);
+               sent = tty->ops->write(tty, cb->buf + cb->offset, cb->len);
                if (sent < 0) {
                        /* error */
                        gig_dbg(DEBUG_OUTPUT, "send_cb: write error %d", sent);
@@ -440,14 +441,14 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, unsi
        struct tty_struct *tty = cs->hw.ser->tty;
        unsigned int set, clear;
 
-       if (!tty || !tty->driver || !tty->driver->tiocmset)
-               return -EFAULT;
+       if (!tty || !tty->driver || !tty->ops->tiocmset)
+               return -EINVAL;
        set = new_state & ~old_state;
        clear = old_state & ~new_state;
        if (!set && !clear)
                return 0;
        gig_dbg(DEBUG_IF, "tiocmset set %x clear %x", set, clear);
-       return tty->driver->tiocmset(tty, NULL, set, clear);
+       return tty->ops->tiocmset(tty, NULL, set, clear);
 }
 
 static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
index 0632a260699858cf7bc7a3036d366b34d888eed5..fae895828a1713317a0286d21f17a4fe6b051a38 100644 (file)
@@ -125,15 +125,11 @@ static const struct file_operations divas_fops = {
 
 int create_divas_proc(void)
 {
-       divas_proc_entry = create_proc_entry(divas_proc_name,
-                                            S_IFREG | S_IRUGO,
-                                            proc_net_eicon);
+       proc_create(divas_proc_name, S_IFREG | S_IRUGO, proc_net_eicon,
+                   &divas_fops);
        if (!divas_proc_entry)
                return (0);
 
-       divas_proc_entry->proc_fops = &divas_fops;
-       divas_proc_entry->owner = THIS_MODULE;
-
        return (1);
 }
 
index 27d890b48f88a6d7d9fab0e78c6a596870391411..877be9922c3d24de4480d77dc25f017e86548092 100644 (file)
@@ -370,6 +370,7 @@ hysdn_conf_close(struct inode *ino, struct file *filep)
 /******************************************************/
 static const struct file_operations conf_fops =
 {
+       .owner          = THIS_MODULE,
        .llseek         = no_llseek,
        .read           = hysdn_conf_read,
        .write          = hysdn_conf_write,
@@ -402,11 +403,9 @@ hysdn_procconf_init(void)
        while (card) {
 
                sprintf(conf_name, "%s%d", PROC_CONF_BASENAME, card->myid);
-               if ((card->procconf = (void *) create_proc_entry(conf_name,
-                                            S_IFREG | S_IRUGO | S_IWUSR,
-                                           hysdn_proc_entry)) != NULL) {
-                       ((struct proc_dir_entry *) card->procconf)->proc_fops = &conf_fops;
-                       ((struct proc_dir_entry *) card->procconf)->owner = THIS_MODULE;
+               if ((card->procconf = (void *) proc_create(conf_name,
+                                               S_IFREG | S_IRUGO | S_IWUSR,
+                                               hysdn_proc_entry)) != NULL) {
                        hysdn_proclog_init(card);       /* init the log file entry */
                }
                card = card->next;      /* next entry */
index 27b3991fb0ec600e031ae1f4627b173fea4a0ce9..8991d2c8ee4a9d74b02e15c9f44246c06593eb63 100644 (file)
@@ -380,6 +380,7 @@ hysdn_log_poll(struct file *file, poll_table * wait)
 /**************************************************/
 static const struct file_operations log_fops =
 {
+       .owner          = THIS_MODULE,
        .llseek         = no_llseek,
        .read           = hysdn_log_read,
        .write          = hysdn_log_write,
@@ -402,10 +403,9 @@ hysdn_proclog_init(hysdn_card * card)
 
        if ((pd = kzalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) {
                sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid);
-               if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL) {
-                       pd->log->proc_fops = &log_fops; 
-                       pd->log->owner = THIS_MODULE;
-               }
+               pd->log = proc_create(pd->log_name,
+                               S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry,
+                               &log_fops);
 
                init_waitqueue_head(&(pd->rd_queue));
 
index 8af0df1d5b8c807c9c57a3c197306ceb74f76c6b..1a2222cbb80541bc492d78cef045f0844a08fad6 100644 (file)
@@ -1352,12 +1352,14 @@ isdn_tty_tiocmget(struct tty_struct *tty, struct file *file)
        if (tty->flags & (1 << TTY_IO_ERROR))
                return -EIO;
 
+       lock_kernel();
 #ifdef ISDN_DEBUG_MODEM_IOCTL
        printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line);
 #endif
 
        control = info->mcr;
        status = info->msr;
+       unlock_kernel();
        return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
            | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
            | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
@@ -1381,6 +1383,7 @@ isdn_tty_tiocmset(struct tty_struct *tty, struct file *file,
        printk(KERN_DEBUG "ttyI%d ioctl TIOCMxxx: %x %x\n", info->line, set, clear);
 #endif
 
+       lock_kernel();
        if (set & TIOCM_RTS)
                info->mcr |= UART_MCR_RTS;
        if (set & TIOCM_DTR) {
@@ -1402,6 +1405,7 @@ isdn_tty_tiocmset(struct tty_struct *tty, struct file *file,
                        isdn_tty_modem_hup(info, 1);
                }
        }
+       unlock_kernel();
        return 0;
 }
 
@@ -1435,21 +1439,6 @@ isdn_tty_ioctl(struct tty_struct *tty, struct file *file,
                                return retval;
                        tty_wait_until_sent(tty, 0);
                        return 0;
-               case TIOCGSOFTCAR:
-#ifdef ISDN_DEBUG_MODEM_IOCTL
-                       printk(KERN_DEBUG "ttyI%d ioctl TIOCGSOFTCAR\n", info->line);
-#endif
-                       return put_user(C_CLOCAL(tty) ? 1 : 0, (ulong __user *) arg);
-               case TIOCSSOFTCAR:
-#ifdef ISDN_DEBUG_MODEM_IOCTL
-                       printk(KERN_DEBUG "ttyI%d ioctl TIOCSSOFTCAR\n", info->line);
-#endif
-                       if (get_user(arg, (ulong __user *) arg))
-                               return -EFAULT;
-                       tty->termios->c_cflag =
-                           ((tty->termios->c_cflag & ~CLOCAL) |
-                            (arg ? CLOCAL : 0));
-                       return 0;
                case TIOCSERGETLSR:     /* Get line status register */
 #ifdef ISDN_DEBUG_MODEM_IOCTL
                        printk(KERN_DEBUG "ttyI%d ioctl TIOCSERGETLSR\n", info->line);
@@ -1472,13 +1461,14 @@ isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
        if (!old_termios)
                isdn_tty_change_speed(info);
        else {
-               if (tty->termios->c_cflag == old_termios->c_cflag)
+               if (tty->termios->c_cflag == old_termios->c_cflag &&
+                   tty->termios->c_ispeed == old_termios->c_ispeed &&
+                   tty->termios->c_ospeed == old_termios->c_ospeed)
                        return;
                isdn_tty_change_speed(info);
                if ((old_termios->c_cflag & CRTSCTS) &&
-                   !(tty->termios->c_cflag & CRTSCTS)) {
+                   !(tty->termios->c_cflag & CRTSCTS))
                        tty->hw_stopped = 0;
-               }
        }
 }
 
@@ -1718,9 +1708,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp)
        }
        dev->modempoll--;
        isdn_tty_shutdown(info);
-       
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       isdn_tty_flush_buffer(tty);
        tty_ldisc_flush(tty);
        info->tty = NULL;
        info->ncarrier = 0;
index ac05a928f7642a54a51a0627e6ca7dc904511d09..b3c54be745568863f8eb5a271ba3e85d4f441f1f 100644 (file)
@@ -105,7 +105,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
 
        led_cdev->dev = device_create(leds_class, parent, 0, "%s",
                                            led_cdev->name);
-       if (unlikely(IS_ERR(led_cdev->dev)))
+       if (IS_ERR(led_cdev->dev))
                return PTR_ERR(led_cdev->dev);
 
        dev_set_drvdata(led_cdev->dev, led_cdev);
index 0c7bfa74c8efccc36502b1cc99c38a542956f6ba..494f0c2001f598aa9af888eeb8a1f5bb4e2e9db8 100644 (file)
@@ -281,24 +281,6 @@ void mca_set_adapter_name(int slot, char* name)
 }
 EXPORT_SYMBOL(mca_set_adapter_name);
 
-/**
- *     mca_is_adapter_used - check if claimed by driver
- *     @slot:  slot to check
- *
- *     Returns 1 if the slot has been claimed by a driver
- */
-
-int mca_is_adapter_used(int slot)
-{
-       struct mca_device *mca_dev = mca_find_device_by_slot(slot);
-
-       if(!mca_dev)
-               return 0;
-
-       return mca_device_claimed(mca_dev);
-}
-EXPORT_SYMBOL(mca_is_adapter_used);
-
 /**
  *     mca_mark_as_used - claim an MCA device
  *     @slot:  slot to claim
index 33d5e0820cc503cc21becb73d11c375c759aaa6a..81ea0d377bf447108825c4683e5b2be633c4b24f 100644 (file)
@@ -183,7 +183,7 @@ void __init mca_do_proc_init(void)
        struct proc_dir_entry* node = NULL;
        struct mca_device *mca_dev;
 
-       proc_mca = proc_mkdir("mca", &proc_root);
+       proc_mca = proc_mkdir("mca", NULL);
        create_proc_read_entry("pos",0,proc_mca,get_mca_info,NULL);
        create_proc_read_entry("machine",0,proc_mca,get_mca_machine_info,NULL);
 
index 6b91b9ab1d41f537bc81e703ecffa710f0efcdf8..3ea5ad4b7805f134af23f9d46842e9a657b7c284 100644 (file)
@@ -110,8 +110,6 @@ static struct request *get_failover_req(struct emc_handler *h,
        memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
        rq->sense_len = 0;
 
-       memset(&rq->cmd, 0, BLK_MAX_CDB);
-
        rq->timeout = EMC_FAILOVER_TIMEOUT;
        rq->cmd_type = REQ_TYPE_BLOCK_PC;
        rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
index 204bf42c94493575518bc72e3536ddc9b94c27de..b63a0ab37c538736c9eac9869fdf464105ba0025 100644 (file)
@@ -137,7 +137,6 @@ static struct request *hp_sw_get_request(struct dm_path *path)
        req->sense = h->sense;
        memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE);
 
-       memset(&req->cmd, 0, BLK_MAX_CDB);
        req->cmd[0] = START_STOP;
        req->cmd[4] = 1;
        req->cmd_len = COMMAND_SIZE(req->cmd[0]);
index e04eb5c697fb884081b79c8ad5ed4b378c19abd6..95e77734880a7ea39b4159359d92f9c42316b843 100644 (file)
@@ -284,7 +284,6 @@ static struct request *get_rdac_req(struct rdac_handler *h,
                return NULL;
        }
 
-       memset(&rq->cmd, 0, BLK_MAX_CDB);
        rq->sense = h->sense;
        memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
        rq->sense_len = 0;
index 51be53344214906593ec54dec6b6e8e1c018f369..94116eaf47099ccad9f8ca458afd3c4f1e835435 100644 (file)
@@ -873,10 +873,11 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q)
        q->max_hw_sectors = t->limits.max_hw_sectors;
        q->seg_boundary_mask = t->limits.seg_boundary_mask;
        q->bounce_pfn = t->limits.bounce_pfn;
+
        if (t->limits.no_cluster)
-               q->queue_flags &= ~(1 << QUEUE_FLAG_CLUSTER);
+               queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q);
        else
-               q->queue_flags |= (1 << QUEUE_FLAG_CLUSTER);
+               queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q);
 
 }
 
index 87620b705bee01182e37cdb0a95bf825f75d77b2..83eb78b00137e98f6624bf72247d8a20bed1f870 100644 (file)
@@ -276,13 +276,15 @@ static mddev_t * mddev_find(dev_t unit)
        init_waitqueue_head(&new->sb_wait);
        new->reshape_position = MaxSector;
        new->resync_max = MaxSector;
+       new->level = LEVEL_NONE;
 
        new->queue = blk_alloc_queue(GFP_KERNEL);
        if (!new->queue) {
                kfree(new);
                return NULL;
        }
-       set_bit(QUEUE_FLAG_CLUSTER, &new->queue->queue_flags);
+       /* Can be unlocked because the queue is new: no concurrency */
+       queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, new->queue);
 
        blk_queue_make_request(new->queue, md_fail_request);
 
@@ -1368,6 +1370,11 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
                MD_BUG();
                return -EINVAL;
        }
+
+       /* prevent duplicates */
+       if (find_rdev(mddev, rdev->bdev->bd_dev))
+               return -EEXIST;
+
        /* make sure rdev->size exceeds mddev->size */
        if (rdev->size && (mddev->size == 0 || rdev->size < mddev->size)) {
                if (mddev->pers) {
@@ -1651,6 +1658,8 @@ static void md_update_sb(mddev_t * mddev, int force_change)
        int sync_req;
        int nospares = 0;
 
+       if (mddev->external)
+               return;
 repeat:
        spin_lock_irq(&mddev->write_lock);
 
@@ -1819,6 +1828,10 @@ state_show(mdk_rdev_t *rdev, char *page)
                len += sprintf(page+len, "%swrite_mostly",sep);
                sep = ",";
        }
+       if (test_bit(Blocked, &rdev->flags)) {
+               len += sprintf(page+len, "%sblocked", sep);
+               sep = ",";
+       }
        if (!test_bit(Faulty, &rdev->flags) &&
            !test_bit(In_sync, &rdev->flags)) {
                len += sprintf(page+len, "%sspare", sep);
@@ -1835,6 +1848,8 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
         *  remove  - disconnects the device
         *  writemostly - sets write_mostly
         *  -writemostly - clears write_mostly
+        *  blocked - sets the Blocked flag
+        *  -blocked - clears the Blocked flag
         */
        int err = -EINVAL;
        if (cmd_match(buf, "faulty") && rdev->mddev->pers) {
@@ -1856,6 +1871,16 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
                err = 0;
        } else if (cmd_match(buf, "-writemostly")) {
                clear_bit(WriteMostly, &rdev->flags);
+               err = 0;
+       } else if (cmd_match(buf, "blocked")) {
+               set_bit(Blocked, &rdev->flags);
+               err = 0;
+       } else if (cmd_match(buf, "-blocked")) {
+               clear_bit(Blocked, &rdev->flags);
+               wake_up(&rdev->blocked_wait);
+               set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery);
+               md_wakeup_thread(rdev->mddev->thread);
+
                err = 0;
        }
        return err ? err : len;
@@ -2096,7 +2121,7 @@ rdev_attr_store(struct kobject *kobj, struct attribute *attr,
                        rv = -EBUSY;
                else
                        rv = entry->store(rdev, page, length);
-               mddev_unlock(rdev->mddev);
+               mddev_unlock(mddev);
        }
        return rv;
 }
@@ -2185,7 +2210,9 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi
                        goto abort_free;
                }
        }
+
        INIT_LIST_HEAD(&rdev->same_set);
+       init_waitqueue_head(&rdev->blocked_wait);
 
        return rdev;
 
@@ -2456,7 +2483,6 @@ resync_start_show(mddev_t *mddev, char *page)
 static ssize_t
 resync_start_store(mddev_t *mddev, const char *buf, size_t len)
 {
-       /* can only set chunk_size if array is not yet active */
        char *e;
        unsigned long long n = simple_strtoull(buf, &e, 10);
 
@@ -2590,15 +2616,20 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
                        err = do_md_stop(mddev, 1);
                else {
                        mddev->ro = 1;
+                       set_disk_ro(mddev->gendisk, 1);
                        err = do_md_run(mddev);
                }
                break;
        case read_auto:
-               /* stopping an active array */
                if (mddev->pers) {
-                       err = do_md_stop(mddev, 1);
-                       if (err == 0)
-                               mddev->ro = 2; /* FIXME mark devices writable */
+                       if (mddev->ro != 1)
+                               err = do_md_stop(mddev, 1);
+                       else
+                               err = restart_array(mddev);
+                       if (err == 0) {
+                               mddev->ro = 2;
+                               set_disk_ro(mddev->gendisk, 0);
+                       }
                } else {
                        mddev->ro = 2;
                        err = do_md_run(mddev);
@@ -2611,6 +2642,8 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
                        if (atomic_read(&mddev->writes_pending) == 0) {
                                if (mddev->in_sync == 0) {
                                        mddev->in_sync = 1;
+                                       if (mddev->safemode == 1)
+                                               mddev->safemode = 0;
                                        if (mddev->persistent)
                                                set_bit(MD_CHANGE_CLEAN,
                                                        &mddev->flags);
@@ -2634,6 +2667,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
                        err = 0;
                } else {
                        mddev->ro = 0;
+                       set_disk_ro(mddev->gendisk, 0);
                        err = do_md_run(mddev);
                }
                break;
@@ -3711,6 +3745,30 @@ static int do_md_stop(mddev_t * mddev, int mode)
                mddev->reshape_position = MaxSector;
                mddev->external = 0;
                mddev->persistent = 0;
+               mddev->level = LEVEL_NONE;
+               mddev->clevel[0] = 0;
+               mddev->flags = 0;
+               mddev->ro = 0;
+               mddev->metadata_type[0] = 0;
+               mddev->chunk_size = 0;
+               mddev->ctime = mddev->utime = 0;
+               mddev->layout = 0;
+               mddev->max_disks = 0;
+               mddev->events = 0;
+               mddev->delta_disks = 0;
+               mddev->new_level = LEVEL_NONE;
+               mddev->new_layout = 0;
+               mddev->new_chunk = 0;
+               mddev->curr_resync = 0;
+               mddev->resync_mismatches = 0;
+               mddev->suspend_lo = mddev->suspend_hi = 0;
+               mddev->sync_speed_min = mddev->sync_speed_max = 0;
+               mddev->recovery = 0;
+               mddev->in_sync = 0;
+               mddev->changed = 0;
+               mddev->degraded = 0;
+               mddev->barriers_work = 0;
+               mddev->safemode = 0;
 
        } else if (mddev->pers)
                printk(KERN_INFO "md: %s switched to read-only mode.\n",
@@ -4918,6 +4976,9 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
 
        if (!rdev || test_bit(Faulty, &rdev->flags))
                return;
+
+       if (mddev->external)
+               set_bit(Blocked, &rdev->flags);
 /*
        dprintk("md_error dev:%s, rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",
                mdname(mddev),
@@ -5364,6 +5425,8 @@ void md_write_start(mddev_t *mddev, struct bio *bi)
                md_wakeup_thread(mddev->sync_thread);
        }
        atomic_inc(&mddev->writes_pending);
+       if (mddev->safemode == 1)
+               mddev->safemode = 0;
        if (mddev->in_sync) {
                spin_lock_irq(&mddev->write_lock);
                if (mddev->in_sync) {
@@ -5718,7 +5781,7 @@ static int remove_and_add_spares(mddev_t *mddev)
 
        rdev_for_each(rdev, rtmp, mddev)
                if (rdev->raid_disk >= 0 &&
-                   !mddev->external &&
+                   !test_bit(Blocked, &rdev->flags) &&
                    (test_bit(Faulty, &rdev->flags) ||
                     ! test_bit(In_sync, &rdev->flags)) &&
                    atomic_read(&rdev->nr_pending)==0) {
@@ -5788,7 +5851,7 @@ void md_check_recovery(mddev_t *mddev)
                return;
 
        if (signal_pending(current)) {
-               if (mddev->pers->sync_request) {
+               if (mddev->pers->sync_request && !mddev->external) {
                        printk(KERN_INFO "md: %s in immediate safe mode\n",
                               mdname(mddev));
                        mddev->safemode = 2;
@@ -5800,7 +5863,7 @@ void md_check_recovery(mddev_t *mddev)
                (mddev->flags && !mddev->external) ||
                test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
                test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
-               (mddev->safemode == 1) ||
+               (mddev->external == 0 && mddev->safemode == 1) ||
                (mddev->safemode == 2 && ! atomic_read(&mddev->writes_pending)
                 && !mddev->in_sync && mddev->recovery_cp == MaxSector)
                ))
@@ -5809,16 +5872,20 @@ void md_check_recovery(mddev_t *mddev)
        if (mddev_trylock(mddev)) {
                int spares = 0;
 
-               spin_lock_irq(&mddev->write_lock);
-               if (mddev->safemode && !atomic_read(&mddev->writes_pending) &&
-                   !mddev->in_sync && mddev->recovery_cp == MaxSector) {
-                       mddev->in_sync = 1;
-                       if (mddev->persistent)
-                               set_bit(MD_CHANGE_CLEAN, &mddev->flags);
+               if (!mddev->external) {
+                       spin_lock_irq(&mddev->write_lock);
+                       if (mddev->safemode &&
+                           !atomic_read(&mddev->writes_pending) &&
+                           !mddev->in_sync &&
+                           mddev->recovery_cp == MaxSector) {
+                               mddev->in_sync = 1;
+                               if (mddev->persistent)
+                                       set_bit(MD_CHANGE_CLEAN, &mddev->flags);
+                       }
+                       if (mddev->safemode == 1)
+                               mddev->safemode = 0;
+                       spin_unlock_irq(&mddev->write_lock);
                }
-               if (mddev->safemode == 1)
-                       mddev->safemode = 0;
-               spin_unlock_irq(&mddev->write_lock);
 
                if (mddev->flags)
                        md_update_sb(mddev, 0);
@@ -5913,6 +5980,16 @@ void md_check_recovery(mddev_t *mddev)
        }
 }
 
+void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
+{
+       sysfs_notify(&rdev->kobj, NULL, "state");
+       wait_event_timeout(rdev->blocked_wait,
+                          !test_bit(Blocked, &rdev->flags),
+                          msecs_to_jiffies(5000));
+       rdev_dec_pending(rdev, mddev);
+}
+EXPORT_SYMBOL(md_wait_for_blocked_rdev);
+
 static int md_notify_reboot(struct notifier_block *this,
                            unsigned long code, void *x)
 {
@@ -5947,13 +6024,9 @@ static struct notifier_block md_notifier = {
 
 static void md_geninit(void)
 {
-       struct proc_dir_entry *p;
-
        dprintk("md: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t));
 
-       p = create_proc_entry("mdstat", S_IRUGO, NULL);
-       if (p)
-               p->proc_fops = &md_seq_fops;
+       proc_create("mdstat", S_IRUGO, NULL, &md_seq_fops);
 }
 
 static int __init md_init(void)
index 9fd473a6dbf51c53e5f1dd3e5cf9c7e0654b547e..6778b7cb39bd5dd94eb719683267a6bef926e3cf 100644 (file)
@@ -773,7 +773,6 @@ static int make_request(struct request_queue *q, struct bio * bio)
        r1bio_t *r1_bio;
        struct bio *read_bio;
        int i, targets = 0, disks;
-       mdk_rdev_t *rdev;
        struct bitmap *bitmap = mddev->bitmap;
        unsigned long flags;
        struct bio_list bl;
@@ -781,6 +780,7 @@ static int make_request(struct request_queue *q, struct bio * bio)
        const int rw = bio_data_dir(bio);
        const int do_sync = bio_sync(bio);
        int do_barriers;
+       mdk_rdev_t *blocked_rdev;
 
        /*
         * Register the new request and wait if the reconstruction
@@ -862,10 +862,17 @@ static int make_request(struct request_queue *q, struct bio * bio)
        first = 0;
        }
 #endif
+ retry_write:
+       blocked_rdev = NULL;
        rcu_read_lock();
        for (i = 0;  i < disks; i++) {
-               if ((rdev=rcu_dereference(conf->mirrors[i].rdev)) != NULL &&
-                   !test_bit(Faulty, &rdev->flags)) {
+               mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
+               if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
+                       atomic_inc(&rdev->nr_pending);
+                       blocked_rdev = rdev;
+                       break;
+               }
+               if (rdev && !test_bit(Faulty, &rdev->flags)) {
                        atomic_inc(&rdev->nr_pending);
                        if (test_bit(Faulty, &rdev->flags)) {
                                rdev_dec_pending(rdev, mddev);
@@ -878,6 +885,20 @@ static int make_request(struct request_queue *q, struct bio * bio)
        }
        rcu_read_unlock();
 
+       if (unlikely(blocked_rdev)) {
+               /* Wait for this device to become unblocked */
+               int j;
+
+               for (j = 0; j < i; j++)
+                       if (r1_bio->bios[j])
+                               rdev_dec_pending(conf->mirrors[j].rdev, mddev);
+
+               allow_barrier(conf);
+               md_wait_for_blocked_rdev(blocked_rdev, mddev);
+               wait_barrier(conf);
+               goto retry_write;
+       }
+
        BUG_ON(targets == 0); /* we never fail the last device */
 
        if (targets < conf->raid_disks) {
index 1e96aa3ff5131f7ec3a39d985a05ccb2a7d7f64a..5938fa9629221145e6b4249d4996ca6c67e08516 100644 (file)
@@ -790,6 +790,7 @@ static int make_request(struct request_queue *q, struct bio * bio)
        const int do_sync = bio_sync(bio);
        struct bio_list bl;
        unsigned long flags;
+       mdk_rdev_t *blocked_rdev;
 
        if (unlikely(bio_barrier(bio))) {
                bio_endio(bio, -EOPNOTSUPP);
@@ -879,17 +880,23 @@ static int make_request(struct request_queue *q, struct bio * bio)
        /*
         * WRITE:
         */
-       /* first select target devices under spinlock and
+       /* first select target devices under rcu_lock and
         * inc refcount on their rdev.  Record them by setting
         * bios[x] to bio
         */
        raid10_find_phys(conf, r10_bio);
+ retry_write:
+       blocked_rdev = 0;
        rcu_read_lock();
        for (i = 0;  i < conf->copies; i++) {
                int d = r10_bio->devs[i].devnum;
                mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[d].rdev);
-               if (rdev &&
-                   !test_bit(Faulty, &rdev->flags)) {
+               if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
+                       atomic_inc(&rdev->nr_pending);
+                       blocked_rdev = rdev;
+                       break;
+               }
+               if (rdev && !test_bit(Faulty, &rdev->flags)) {
                        atomic_inc(&rdev->nr_pending);
                        r10_bio->devs[i].bio = bio;
                } else {
@@ -899,6 +906,22 @@ static int make_request(struct request_queue *q, struct bio * bio)
        }
        rcu_read_unlock();
 
+       if (unlikely(blocked_rdev)) {
+               /* Have to wait for this device to get unblocked, then retry */
+               int j;
+               int d;
+
+               for (j = 0; j < i; j++)
+                       if (r10_bio->devs[j].bio) {
+                               d = r10_bio->devs[j].devnum;
+                               rdev_dec_pending(conf->mirrors[d].rdev, mddev);
+                       }
+               allow_barrier(conf);
+               md_wait_for_blocked_rdev(blocked_rdev, mddev);
+               wait_barrier(conf);
+               goto retry_write;
+       }
+
        atomic_set(&r10_bio->remaining, 0);
 
        bio_list_init(&bl);
index 968dacaced6de669181bba2d1e1902fbea3ffa8f..087eee0cb80913fabc692187eed59e981c5eb95e 100644 (file)
@@ -2607,6 +2607,7 @@ static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh,
        }
 }
 
+
 /*
  * handle_stripe - do things to a stripe.
  *
@@ -2632,6 +2633,7 @@ static void handle_stripe5(struct stripe_head *sh)
        struct stripe_head_state s;
        struct r5dev *dev;
        unsigned long pending = 0;
+       mdk_rdev_t *blocked_rdev = NULL;
 
        memset(&s, 0, sizeof(s));
        pr_debug("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d "
@@ -2691,6 +2693,11 @@ static void handle_stripe5(struct stripe_head *sh)
                if (dev->written)
                        s.written++;
                rdev = rcu_dereference(conf->disks[i].rdev);
+               if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
+                       blocked_rdev = rdev;
+                       atomic_inc(&rdev->nr_pending);
+                       break;
+               }
                if (!rdev || !test_bit(In_sync, &rdev->flags)) {
                        /* The ReadError flag will just be confusing now */
                        clear_bit(R5_ReadError, &dev->flags);
@@ -2705,6 +2712,11 @@ static void handle_stripe5(struct stripe_head *sh)
        }
        rcu_read_unlock();
 
+       if (unlikely(blocked_rdev)) {
+               set_bit(STRIPE_HANDLE, &sh->state);
+               goto unlock;
+       }
+
        if (s.to_fill && !test_and_set_bit(STRIPE_OP_BIOFILL, &sh->ops.pending))
                sh->ops.count++;
 
@@ -2894,8 +2906,13 @@ static void handle_stripe5(struct stripe_head *sh)
        if (sh->ops.count)
                pending = get_stripe_work(sh);
 
+ unlock:
        spin_unlock(&sh->lock);
 
+       /* wait for this device to become unblocked */
+       if (unlikely(blocked_rdev))
+               md_wait_for_blocked_rdev(blocked_rdev, conf->mddev);
+
        if (pending)
                raid5_run_ops(sh, pending);
 
@@ -2912,6 +2929,7 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
        struct stripe_head_state s;
        struct r6_state r6s;
        struct r5dev *dev, *pdev, *qdev;
+       mdk_rdev_t *blocked_rdev = NULL;
 
        r6s.qd_idx = raid6_next_disk(pd_idx, disks);
        pr_debug("handling stripe %llu, state=%#lx cnt=%d, "
@@ -2975,6 +2993,11 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
                if (dev->written)
                        s.written++;
                rdev = rcu_dereference(conf->disks[i].rdev);
+               if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
+                       blocked_rdev = rdev;
+                       atomic_inc(&rdev->nr_pending);
+                       break;
+               }
                if (!rdev || !test_bit(In_sync, &rdev->flags)) {
                        /* The ReadError flag will just be confusing now */
                        clear_bit(R5_ReadError, &dev->flags);
@@ -2989,6 +3012,11 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
                        set_bit(R5_Insync, &dev->flags);
        }
        rcu_read_unlock();
+
+       if (unlikely(blocked_rdev)) {
+               set_bit(STRIPE_HANDLE, &sh->state);
+               goto unlock;
+       }
        pr_debug("locked=%d uptodate=%d to_read=%d"
               " to_write=%d failed=%d failed_num=%d,%d\n",
               s.locked, s.uptodate, s.to_read, s.to_write, s.failed,
@@ -3094,8 +3122,13 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
            !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending))
                handle_stripe_expansion(conf, sh, &r6s);
 
+ unlock:
        spin_unlock(&sh->lock);
 
+       /* wait for this device to become unblocked */
+       if (unlikely(blocked_rdev))
+               md_wait_for_blocked_rdev(blocked_rdev, conf->mddev);
+
        return_io(return_bi);
 
        for (i=disks; i-- ;) {
index 128bb9cd5755f57f7a8cab9895149edcb39680aa..ddf57e135c6c61633fa030dd623a67d5072491c0 100644 (file)
@@ -5,16 +5,20 @@
 menu "Multimedia devices"
        depends on HAS_IOMEM
 
+comment "Multimedia core support"
+
+#
+# V4L core and enabled API's
+#
+
 config VIDEO_DEV
        tristate "Video For Linux"
        ---help---
-         Support for audio/video capture and overlay devices and FM radio
-         cards. The exact capabilities of each device vary.
+         V4L core support for video capture and overlay devices, webcams and
+         AM/FM radio cards.
 
          This kernel includes support for the new Video for Linux Two API,
-         (V4L2) as well as the original system. Drivers and applications
-         need to be rewritten to use V4L2, but drivers for popular cards
-         and applications for most video capture functions already exist.
+         (V4L2).
 
          Additional info and docs are available on the web at
          <http://linuxtv.org>
@@ -36,8 +40,11 @@ config VIDEO_ALLOW_V4L1
        default VIDEO_DEV && VIDEO_V4L2_COMMON
        select VIDEO_V4L1_COMPAT
        ---help---
-         Enables a compatibility API used by most V4L2 devices to allow
-         its usage with legacy applications that supports only V4L1 api.
+         Enables drivers based on the legacy V4L1 API.
+
+         This api were developed to be used at Kernel 2.2 and 2.4, but
+         lacks support for several video standards. There are several
+         drivers at kernel that still depends on it.
 
          If you are unsure as to whether this is required, answer Y.
 
@@ -46,9 +53,8 @@ config VIDEO_V4L1_COMPAT
        depends on VIDEO_DEV
        default VIDEO_DEV
        ---help---
-         This api were developed to be used at Kernel 2.2 and 2.4, but
-         lacks support for several video standards. There are several
-         drivers at kernel that still depends on it.
+         Enables a compatibility API used by most V4L2 devices to allow
+         its usage with legacy applications that supports only V4L1 api.
 
          Documentation for the original API is included in the file
          <Documentation/video4linux/API.html>.
@@ -58,135 +64,57 @@ config VIDEO_V4L1_COMPAT
 
          If you are unsure as to whether this is required, answer Y.
 
-config VIDEO_V4L2
-       tristate
-       depends on VIDEO_DEV && VIDEO_V4L2_COMMON
-       default VIDEO_DEV && VIDEO_V4L2_COMMON
-
-config VIDEO_V4L1
-       tristate
-       depends on VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
-       default VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
-
-source "drivers/media/video/Kconfig"
-
-source "drivers/media/radio/Kconfig"
-
-source "drivers/media/dvb/Kconfig"
-
-source "drivers/media/common/Kconfig"
+#
+# DVB Core
+#
 
-config VIDEO_TUNER
-       tristate
-       depends on I2C
-       select TUNER_XC2028 if !VIDEO_TUNER_CUSTOMIZE
-       select TUNER_MT20XX if !VIDEO_TUNER_CUSTOMIZE
-       select TUNER_TDA8290 if !VIDEO_TUNER_CUSTOMIZE
-       select TUNER_TEA5761 if !VIDEO_TUNER_CUSTOMIZE
-       select TUNER_TEA5767 if !VIDEO_TUNER_CUSTOMIZE
-       select TUNER_SIMPLE if !VIDEO_TUNER_CUSTOMIZE
-       select TUNER_TDA9887 if !VIDEO_TUNER_CUSTOMIZE
-
-menuconfig VIDEO_TUNER_CUSTOMIZE
-       bool "Customize analog tuner modules to build"
-       depends on VIDEO_TUNER
+config DVB_CORE
+       tristate "DVB for Linux"
+       depends on NET && INET
+       select CRC32
        help
-         This allows the user to deselect tuner drivers unnecessary
-         for their hardware from the build. Use this option with care
-         as deselecting tuner drivers which are in fact necessary will
-         result in V4L devices which cannot be tuned due to lack of
-         driver support
+         DVB core utility functions for device handling, software fallbacks etc.
 
-         If unsure say N.
-
-if VIDEO_TUNER_CUSTOMIZE
-
-config TUNER_XC2028
-       tristate "XCeive xc2028/xc3028 tuners"
-       depends on I2C && FW_LOADER
-       default m if VIDEO_TUNER_CUSTOMIZE
-       help
-         Say Y here to include support for the xc2028/xc3028 tuners.
+         Enable this if you own a DVB/ATSC adapter and want to use it or if
+         you compile Linux for a digital SetTopBox.
 
-config TUNER_MT20XX
-       tristate "Microtune 2032 / 2050 tuners"
-       depends on I2C
-       default m if VIDEO_TUNER_CUSTOMIZE
-       help
-         Say Y here to include support for the MT2032 / MT2050 tuner.
-
-config TUNER_TDA8290
-       tristate "TDA 8290/8295 + 8275(a)/18271 tuner combo"
-       depends on I2C
-       select DVB_TDA827X
-       select DVB_TDA18271
-       default m if VIDEO_TUNER_CUSTOMIZE
-       help
-         Say Y here to include support for Philips TDA8290+8275(a) tuner.
+         Say Y when you have a DVB or an ATSC card and want to use it.
 
-config TUNER_TEA5761
-       tristate "TEA 5761 radio tuner (EXPERIMENTAL)"
-       depends on I2C && EXPERIMENTAL
-       default m if VIDEO_TUNER_CUSTOMIZE
-       help
-         Say Y here to include support for the Philips TEA5761 radio tuner.
+         API specs and user tools are available from <http://www.linuxtv.org/>.
 
-config TUNER_TEA5767
-       tristate "TEA 5767 radio tuner"
-       depends on I2C
-       default m if VIDEO_TUNER_CUSTOMIZE
-       help
-         Say Y here to include support for the Philips TEA5767 radio tuner.
+         Please report problems regarding this support to the LinuxDVB
+         mailing list.
 
-config TUNER_SIMPLE
-       tristate "Simple tuner support"
-       depends on I2C
-       select TUNER_TDA9887
-       default m if VIDEO_TUNER_CUSTOMIZE
-       help
-         Say Y here to include support for various simple tuners.
+         If unsure say N.
 
-config TUNER_TDA9887
-       tristate "TDA 9885/6/7 analog IF demodulator"
-       depends on I2C
-       default m if VIDEO_TUNER_CUSTOMIZE
-       help
-         Say Y here to include support for Philips TDA9885/6/7
-         analog IF demodulator.
+config VIDEO_MEDIA
+       tristate
+       default DVB_CORE || VIDEO_DEV
+       depends on DVB_CORE || VIDEO_DEV
 
-endif # VIDEO_TUNER_CUSTOMIZE
+comment "Multimedia drivers"
 
-config VIDEOBUF_GEN
-       tristate
+source "drivers/media/common/Kconfig"
 
-config VIDEOBUF_DMA_SG
-       depends on HAS_DMA
-       select VIDEOBUF_GEN
-       tristate
+#
+# Tuner drivers for DVB and V4L
+#
 
-config VIDEOBUF_VMALLOC
-       select VIDEOBUF_GEN
-       tristate
+source "drivers/media/common/tuners/Kconfig"
 
-config VIDEOBUF_DVB
-       tristate
-       select VIDEOBUF_GEN
-       select VIDEOBUF_DMA_SG
+#
+# Video/Radio/Hybrid adapters
+#
 
-config VIDEO_BTCX
-       tristate
+source "drivers/media/video/Kconfig"
 
-config VIDEO_IR_I2C
-       tristate
+source "drivers/media/radio/Kconfig"
 
-config VIDEO_IR
-       tristate
-       depends on INPUT
-       select VIDEO_IR_I2C if I2C
+#
+# DVB adapters
+#
 
-config VIDEO_TVEEPROM
-       tristate
-       depends on I2C
+source "drivers/media/dvb/Kconfig"
 
 config DAB
        boolean "DAB adapters"
index 7b8bb6949f5e877262312666a4991bf46c957c81..73f742c7e818428f1965d880a3c442e71154a957 100644 (file)
@@ -2,10 +2,10 @@
 # Makefile for the kernel multimedia device drivers.
 #
 
-obj-y := common/
-obj-y += video/
+obj-$(CONFIG_VIDEO_MEDIA) += common/
+
+# Since hybrid devices are here, should be compiled if DVB and/or V4L
+obj-$(CONFIG_VIDEO_MEDIA) += video/
+
 obj-$(CONFIG_VIDEO_DEV) += radio/
 obj-$(CONFIG_DVB_CORE)  += dvb/
-ifeq ($(CONFIG_DVB_CORE),)
-  obj-$(CONFIG_VIDEO_TUNER)  += dvb/frontends/
-endif
index 8e744823064382309cbf35a20cfbb41c30842b7e..351b98b9b302a765169ef2aa97050bfa7deeab0d 100644 (file)
@@ -2,6 +2,7 @@ saa7146-objs    := saa7146_i2c.o saa7146_core.o
 saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o
 ir-common-objs  := ir-functions.o ir-keymaps.o
 
+obj-y += tuners/
 obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o
 obj-$(CONFIG_VIDEO_SAA7146_VV) += saa7146_vv.o
 obj-$(CONFIG_VIDEO_IR) += ir-common.o
diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig
new file mode 100644 (file)
index 0000000..5be85ff
--- /dev/null
@@ -0,0 +1,151 @@
+config MEDIA_ATTACH
+       bool "Load and attach frontend and tuner driver modules as needed"
+       depends on DVB_CORE
+       depends on MODULES
+       help
+         Remove the static dependency of DVB card drivers on all
+         frontend modules for all possible card variants. Instead,
+         allow the card drivers to only load the frontend modules
+         they require.
+
+         Also, tuner module will automatically load a tuner driver
+         when needed, for analog mode.
+
+         This saves several KBytes of memory.
+
+         Note: You will need module-init-tools v3.2 or later for this feature.
+
+         If unsure say Y.
+
+config MEDIA_TUNER
+       tristate
+       default DVB_CORE || VIDEO_DEV
+       depends on DVB_CORE || VIDEO_DEV
+       select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE
+       select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE
+       select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMIZE
+       select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE
+       select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMIZE
+       select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMIZE
+       select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE
+       select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMIZE
+
+menuconfig MEDIA_TUNER_CUSTOMIZE
+       bool "Customize analog and hybrid tuner modules to build"
+       depends on MEDIA_TUNER
+       help
+         This allows the user to deselect tuner drivers unnecessary
+         for their hardware from the build. Use this option with care
+         as deselecting tuner drivers which are in fact necessary will
+         result in V4L/DVB devices which cannot be tuned due to lack of
+         driver support
+
+         If unsure say N.
+
+if MEDIA_TUNER_CUSTOMIZE
+
+config MEDIA_TUNER_SIMPLE
+       tristate "Simple tuner support"
+       depends on I2C
+       select MEDIA_TUNER_TDA9887
+       default m if MEDIA_TUNER_CUSTOMIZE
+       help
+         Say Y here to include support for various simple tuners.
+
+config MEDIA_TUNER_TDA8290
+       tristate "TDA 8290/8295 + 8275(a)/18271 tuner combo"
+       depends on I2C
+       select MEDIA_TUNER_TDA827X
+       select MEDIA_TUNER_TDA18271
+       default m if MEDIA_TUNER_CUSTOMIZE
+       help
+         Say Y here to include support for Philips TDA8290+8275(a) tuner.
+
+config MEDIA_TUNER_TDA827X
+       tristate "Philips TDA827X silicon tuner"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A DVB-T silicon tuner module. Say Y when you want to support this tuner.
+
+config MEDIA_TUNER_TDA18271
+       tristate "NXP TDA18271 silicon tuner"
+       depends on I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A silicon tuner module. Say Y when you want to support this tuner.
+
+config MEDIA_TUNER_TDA9887
+       tristate "TDA 9885/6/7 analog IF demodulator"
+       depends on I2C
+       default m if MEDIA_TUNER_CUSTOMIZE
+       help
+         Say Y here to include support for Philips TDA9885/6/7
+         analog IF demodulator.
+
+config MEDIA_TUNER_TEA5761
+       tristate "TEA 5761 radio tuner (EXPERIMENTAL)"
+       depends on I2C && EXPERIMENTAL
+       default m if MEDIA_TUNER_CUSTOMIZE
+       help
+         Say Y here to include support for the Philips TEA5761 radio tuner.
+
+config MEDIA_TUNER_TEA5767
+       tristate "TEA 5767 radio tuner"
+       depends on I2C
+       default m if MEDIA_TUNER_CUSTOMIZE
+       help
+         Say Y here to include support for the Philips TEA5767 radio tuner.
+
+config MEDIA_TUNER_MT20XX
+       tristate "Microtune 2032 / 2050 tuners"
+       depends on I2C
+       default m if MEDIA_TUNER_CUSTOMIZE
+       help
+         Say Y here to include support for the MT2032 / MT2050 tuner.
+
+config MEDIA_TUNER_MT2060
+       tristate "Microtune MT2060 silicon IF tuner"
+       depends on I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A driver for the silicon IF tuner MT2060 from Microtune.
+
+config MEDIA_TUNER_MT2266
+       tristate "Microtune MT2266 silicon tuner"
+       depends on I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A driver for the silicon baseband tuner MT2266 from Microtune.
+
+config MEDIA_TUNER_MT2131
+       tristate "Microtune MT2131 silicon tuner"
+       depends on I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A driver for the silicon baseband tuner MT2131 from Microtune.
+
+config MEDIA_TUNER_QT1010
+       tristate "Quantek QT1010 silicon tuner"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A driver for the silicon tuner QT1010 from Quantek.
+
+config MEDIA_TUNER_XC2028
+       tristate "XCeive xc2028/xc3028 tuners"
+       depends on I2C && FW_LOADER
+       default m if MEDIA_TUNER_CUSTOMIZE
+       help
+         Say Y here to include support for the xc2028/xc3028 tuners.
+
+config MEDIA_TUNER_XC5000
+       tristate "Xceive XC5000 silicon tuner"
+       depends on I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A driver for the silicon tuner XC5000 from Xceive.
+         This device is only used inside a SiP called togther with a
+         demodulator for now.
+
+endif # MEDIA_TUNER_CUSTOMIZE
diff --git a/drivers/media/common/tuners/Makefile b/drivers/media/common/tuners/Makefile
new file mode 100644 (file)
index 0000000..236d993
--- /dev/null
@@ -0,0 +1,25 @@
+#
+# Makefile for common V4L/DVB tuners
+#
+
+tda18271-objs := tda18271-maps.o tda18271-common.o tda18271-fe.o
+
+obj-$(CONFIG_MEDIA_TUNER_XC2028) += tuner-xc2028.o
+obj-$(CONFIG_MEDIA_TUNER_SIMPLE) += tuner-simple.o
+# tuner-types will be merged into tuner-simple, in the future
+obj-$(CONFIG_MEDIA_TUNER_SIMPLE) += tuner-types.o
+obj-$(CONFIG_MEDIA_TUNER_MT20XX) += mt20xx.o
+obj-$(CONFIG_MEDIA_TUNER_TDA8290) += tda8290.o
+obj-$(CONFIG_MEDIA_TUNER_TEA5767) += tea5767.o
+obj-$(CONFIG_MEDIA_TUNER_TEA5761) += tea5761.o
+obj-$(CONFIG_MEDIA_TUNER_TDA9887) += tda9887.o
+obj-$(CONFIG_MEDIA_TUNER_TDA827X) += tda827x.o
+obj-$(CONFIG_MEDIA_TUNER_TDA18271) += tda18271.o
+obj-$(CONFIG_MEDIA_TUNER_XC5000) += xc5000.o
+obj-$(CONFIG_MEDIA_TUNER_MT2060) += mt2060.o
+obj-$(CONFIG_MEDIA_TUNER_MT2266) += mt2266.o
+obj-$(CONFIG_MEDIA_TUNER_QT1010) += qt1010.o
+obj-$(CONFIG_MEDIA_TUNER_MT2131) += mt2131.o
+
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
similarity index 90%
rename from drivers/media/dvb/frontends/mt2060.h
rename to drivers/media/common/tuners/mt2060.h
index acba0058f519bf00403a78b56b369de56f8c6a9c..cb60caffb6b6ae2c1ad4a10bf7eb95a474ef458a 100644 (file)
@@ -30,7 +30,7 @@ struct mt2060_config {
        u8 clock_out; /* 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1 */
 };
 
-#if defined(CONFIG_DVB_TUNER_MT2060) || (defined(CONFIG_DVB_TUNER_MT2060_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_MT2060) || (defined(CONFIG_MEDIA_TUNER_MT2060_MODULE) && defined(MODULE))
 extern struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1);
 #else
 static inline struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1)
@@ -38,6 +38,6 @@ static inline struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struc
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
-#endif // CONFIG_DVB_TUNER_MT2060
+#endif // CONFIG_MEDIA_TUNER_MT2060
 
 #endif
similarity index 91%
rename from drivers/media/video/mt20xx.h
rename to drivers/media/common/tuners/mt20xx.h
index aa848e14ce5e75bbf43b8edecc057fdc209af33b..259553a24903c3a9a1b59ca40ab7a8f936149fc3 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/i2c.h>
 #include "dvb_frontend.h"
 
-#if defined(CONFIG_TUNER_MT20XX) || (defined(CONFIG_TUNER_MT20XX_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_MT20XX) || (defined(CONFIG_MEDIA_TUNER_MT20XX_MODULE) && defined(MODULE))
 extern struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
                                             struct i2c_adapter* i2c_adap,
                                             u8 i2c_addr);
similarity index 91%
rename from drivers/media/dvb/frontends/mt2131.h
rename to drivers/media/common/tuners/mt2131.h
index 606d8576bc9885d2a7d8a9c504d41efcb860be76..cd8376f6f7b48ac3fd812e7ee7f06eb8cf037a3e 100644 (file)
@@ -30,7 +30,7 @@ struct mt2131_config {
        u8 clock_out; /* 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1 */
 };
 
-#if defined(CONFIG_DVB_TUNER_MT2131) || (defined(CONFIG_DVB_TUNER_MT2131_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_MT2131) || (defined(CONFIG_MEDIA_TUNER_MT2131_MODULE) && defined(MODULE))
 extern struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
                                          struct i2c_adapter *i2c,
                                          struct mt2131_config *cfg,
@@ -44,7 +44,7 @@ static inline struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
-#endif /* CONFIG_DVB_TUNER_MT2131 */
+#endif /* CONFIG_MEDIA_TUNER_MT2131 */
 
 #endif /* __MT2131_H__ */
 
similarity index 88%
rename from drivers/media/dvb/frontends/mt2266.h
rename to drivers/media/common/tuners/mt2266.h
index c5113efe333c745a0e66919827a88b42073f3719..4d083882d044a6a6dcd96bb115651c7ad956ba50 100644 (file)
@@ -24,7 +24,7 @@ struct mt2266_config {
        u8 i2c_address;
 };
 
-#if defined(CONFIG_DVB_TUNER_MT2266) || (defined(CONFIG_DVB_TUNER_MT2266_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_MT2266) || (defined(CONFIG_MEDIA_TUNER_MT2266_MODULE) && defined(MODULE))
 extern struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg);
 #else
 static inline struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg)
@@ -32,6 +32,6 @@ static inline struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struc
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
-#endif // CONFIG_DVB_TUNER_MT2266
+#endif // CONFIG_MEDIA_TUNER_MT2266
 
 #endif
similarity index 91%
rename from drivers/media/dvb/frontends/qt1010.h
rename to drivers/media/common/tuners/qt1010.h
index cff6a7ca53801cce4335b41a24c8f29f7cf93a0a..807fb7b6146b94984fc597298705e7b04e7cb678 100644 (file)
@@ -36,7 +36,7 @@ struct qt1010_config {
  * @param cfg  tuner hw based configuration
  * @return fe  pointer on success, NULL on failure
  */
-#if defined(CONFIG_DVB_TUNER_QT1010) || (defined(CONFIG_DVB_TUNER_QT1010_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_QT1010) || (defined(CONFIG_MEDIA_TUNER_QT1010_MODULE) && defined(MODULE))
 extern struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe,
                                          struct i2c_adapter *i2c,
                                          struct qt1010_config *cfg);
@@ -48,6 +48,6 @@ static inline struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe,
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
-#endif // CONFIG_DVB_TUNER_QT1010
+#endif // CONFIG_MEDIA_TUNER_QT1010
 
 #endif
similarity index 96%
rename from drivers/media/dvb/frontends/tda18271.h
rename to drivers/media/common/tuners/tda18271.h
index 0e7af8d05a38cb91c074b7310bad34b93ad33073..7db9831c0cb073a0b75bf04d7bd0e745ec92f10b 100644 (file)
@@ -81,7 +81,7 @@ struct tda18271_config {
        unsigned int small_i2c:1;
 };
 
-#if defined(CONFIG_DVB_TDA18271) || (defined(CONFIG_DVB_TDA18271_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_TDA18271) || (defined(CONFIG_MEDIA_TUNER_TDA18271_MODULE) && defined(MODULE))
 extern struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
                                            struct i2c_adapter *i2c,
                                            struct tda18271_config *cfg);
similarity index 93%
rename from drivers/media/dvb/frontends/tda827x.h
rename to drivers/media/common/tuners/tda827x.h
index b73c23570dab67e094482ebf31b77dcea29d4fe3..7850a9a1dc8f42a04a0e2c19496b894aeb8611a6 100644 (file)
@@ -51,7 +51,7 @@ struct tda827x_config
  * @param cfg optional callback function pointers.
  * @return FE pointer on success, NULL on failure.
  */
-#if defined(CONFIG_DVB_TDA827X) || (defined(CONFIG_DVB_TDA827X_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_TDA827X) || (defined(CONFIG_MEDIA_TUNER_TDA827X_MODULE) && defined(MODULE))
 extern struct dvb_frontend* tda827x_attach(struct dvb_frontend *fe, int addr,
                                           struct i2c_adapter *i2c,
                                           struct tda827x_config *cfg);
@@ -64,6 +64,6 @@ static inline struct dvb_frontend* tda827x_attach(struct dvb_frontend *fe,
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
-#endif // CONFIG_DVB_TDA827X
+#endif // CONFIG_MEDIA_TUNER_TDA827X
 
 #endif // __DVB_TDA827X_H__
similarity index 99%
rename from drivers/media/video/tda8290.c
rename to drivers/media/common/tuners/tda8290.c
index 0ebb5b525e576da86f021b74b669f5493e4886db..91204d3f282dfc5de1c02c7c9b9ad6c62959ff13 100644 (file)
@@ -578,16 +578,16 @@ static int tda829x_find_tuner(struct dvb_frontend *fe)
 
        if ((data == 0x83) || (data == 0x84)) {
                priv->ver |= TDA18271;
-               tda18271_attach(fe, priv->tda827x_addr,
-                               priv->i2c_props.adap,
-                               &tda829x_tda18271_config);
+               dvb_attach(tda18271_attach, fe, priv->tda827x_addr,
+                          priv->i2c_props.adap, &tda829x_tda18271_config);
        } else {
                if ((data & 0x3c) == 0)
                        priv->ver |= TDA8275;
                else
                        priv->ver |= TDA8275A;
 
-               tda827x_attach(fe, priv->tda827x_addr, priv->i2c_props.adap, &priv->cfg);
+               dvb_attach(tda827x_attach, fe, priv->tda827x_addr,
+                          priv->i2c_props.adap, &priv->cfg);
                priv->cfg.switch_addr = priv->i2c_props.addr;
        }
        if (fe->ops.tuner_ops.init)
similarity index 94%
rename from drivers/media/video/tda8290.h
rename to drivers/media/common/tuners/tda8290.h
index d3bbf276a469165354e82770764feec9d619bec6..aa074f3f0c07f247db9e74a6fe4e636488ad0d47 100644 (file)
@@ -29,7 +29,7 @@ struct tda829x_config {
 #define TDA829X_DONT_PROBE  1
 };
 
-#if defined(CONFIG_TUNER_TDA8290) || (defined(CONFIG_TUNER_TDA8290_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_TDA8290) || (defined(CONFIG_MEDIA_TUNER_TDA8290_MODULE) && defined(MODULE))
 extern int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr);
 
 extern struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
similarity index 92%
rename from drivers/media/video/tda9887.h
rename to drivers/media/common/tuners/tda9887.h
index be49dcbfc70e1473056823b24e7a7f0d7bec56d2..acc419e8c4fcfb858e66b7e5c00449d9d80f40e8 100644 (file)
@@ -21,7 +21,7 @@
 #include "dvb_frontend.h"
 
 /* ------------------------------------------------------------------------ */
-#if defined(CONFIG_TUNER_TDA9887) || (defined(CONFIG_TUNER_TDA9887_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_TDA9887) || (defined(CONFIG_MEDIA_TUNER_TDA9887_MODULE) && defined(MODULE))
 extern struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
                                           struct i2c_adapter *i2c_adap,
                                           u8 i2c_addr);
similarity index 93%
rename from drivers/media/video/tea5761.h
rename to drivers/media/common/tuners/tea5761.h
index 8eb62722b9885f7d4253200a128401b416736c65..2e2ff82c95a4f7dd81a337980dcfda235aa1c669 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/i2c.h>
 #include "dvb_frontend.h"
 
-#if defined(CONFIG_TUNER_TEA5761) || (defined(CONFIG_TUNER_TEA5761_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_TEA5761) || (defined(CONFIG_MEDIA_TUNER_TEA5761_MODULE) && defined(MODULE))
 extern int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr);
 
 extern struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
similarity index 94%
rename from drivers/media/video/tea5767.h
rename to drivers/media/common/tuners/tea5767.h
index 7b547c092e25215bbd81505b8635c7ec907611bc..d30ab1b483de68daeb70944bc748400ecac0f25f 100644 (file)
@@ -39,7 +39,7 @@ struct tea5767_ctrl {
        enum tea5767_xtal       xtal_freq;
 };
 
-#if defined(CONFIG_TUNER_TEA5767) || (defined(CONFIG_TUNER_TEA5767_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_TEA5767) || (defined(CONFIG_MEDIA_TUNER_TEA5767_MODULE) && defined(MODULE))
 extern int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr);
 
 extern struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
similarity index 92%
rename from drivers/media/video/tuner-simple.h
rename to drivers/media/common/tuners/tuner-simple.h
index e46cf0121e030a23e314190116567550f9c7ff7e..381fa5d35a9bb6617b6d610b780552c3da442af1 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/i2c.h>
 #include "dvb_frontend.h"
 
-#if defined(CONFIG_TUNER_SIMPLE) || (defined(CONFIG_TUNER_SIMPLE_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_SIMPLE) || (defined(CONFIG_MEDIA_TUNER_SIMPLE_MODULE) && defined(MODULE))
 extern struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
                                                struct i2c_adapter *i2c_adap,
                                                u8 i2c_addr,
similarity index 93%
rename from drivers/media/video/tuner-xc2028.h
rename to drivers/media/common/tuners/tuner-xc2028.h
index fc2f132a5541279e9c1b6089535dd42fd21fbb69..216025cf5d4bfdbe430851636818c69789987cab 100644 (file)
@@ -47,7 +47,7 @@ struct xc2028_config {
 #define XC2028_TUNER_RESET     0
 #define XC2028_RESET_CLK       1
 
-#if defined(CONFIG_TUNER_XC2028) || (defined(CONFIG_TUNER_XC2028_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_XC2028) || (defined(CONFIG_MEDIA_TUNER_XC2028_MODULE) && defined(MODULE))
 extern struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
                                          struct xc2028_config *cfg);
 #else
similarity index 92%
rename from drivers/media/dvb/frontends/xc5000.h
rename to drivers/media/common/tuners/xc5000.h
index b890883a0cdc224a8f888000564b7eb4f63635bc..0ee80f9d19b8fa8621acb2f919650cc266925ae2 100644 (file)
@@ -45,8 +45,8 @@ struct xc5000_config {
 /* xc5000 callback command */
 #define XC5000_TUNER_RESET             0
 
-#if defined(CONFIG_DVB_TUNER_XC5000) || \
-    (defined(CONFIG_DVB_TUNER_XC5000_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_XC5000) || \
+    (defined(CONFIG_MEDIA_TUNER_XC5000_MODULE) && defined(MODULE))
 extern struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
                                          struct i2c_adapter *i2c,
                                          struct xc5000_config *cfg);
@@ -58,6 +58,6 @@ static inline struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe,
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
-#endif // CONFIG_DVB_TUNER_XC5000
+#endif // CONFIG_MEDIA_TUNER_XC5000
 
 #endif // __XC5000_H__
index 03ef88acd9b826bbafc60ccad5a12be6e0302ceb..7b21b49f1945ad56430f6bf16ac99bdaed89f52b 100644 (file)
@@ -1,9 +1,7 @@
 #
-# Multimedia device configuration
+# DVB device configuration
 #
 
-source "drivers/media/dvb/dvb-core/Kconfig"
-
 menuconfig DVB_CAPTURE_DRIVERS
        bool "DVB/ATSC adapters"
        depends on DVB_CORE
index 6ec5afba1ca7ee061779067f22b36ad352d43b96..73dc2ee9b014021a5681d83be1badd96802010bc 100644 (file)
@@ -9,7 +9,7 @@ config DVB_B2C2_FLEXCOP
        select DVB_STV0297 if !DVB_FE_CUSTOMISE
        select DVB_BCM3510 if !DVB_FE_CUSTOMISE
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
-       select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
        select DVB_S5H1420 if !DVB_FE_CUSTOMISE
        select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE
        select DVB_ISL6421 if !DVB_FE_CUSTOMISE
index 870e2848c2962418b343ef2ae4ae5fcc561c0a5d..d9db066f9854f19a7572848b8834c0c1c29ee6a0 100644 (file)
@@ -14,4 +14,4 @@ b2c2-flexcop-usb-objs = flexcop-usb.o
 obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
-EXTRA_CFLAGS += -Idrivers/media/video/
+EXTRA_CFLAGS += -Idrivers/media/common/tuners/
index 902c762e0b7fb8867bc1d62ea65f2e2a4ee5e9a3..d1239b8342f81cdb13b5642fedcf463655fc1cb6 100644 (file)
@@ -8,7 +8,7 @@ config DVB_BT8XX
        select DVB_OR51211 if !DVB_FE_CUSTOMISE
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
        select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-       select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
        select FW_LOADER
        help
          Support for PCI cards based on the Bt8xx PCI bridge. Examples are
index 9d3e68b5d6ebc22e9b8fb4adfdbf42aa50784d20..d98f1d49ffa89bab91f5c936189b7adc445f1c80 100644 (file)
@@ -3,4 +3,4 @@ obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
 EXTRA_CFLAGS += -Idrivers/media/video/bt8xx
-EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
index 75711bde23ad3675fe82f89bf6f4edf68d7db644..a7637562e74200943bb846dddf81a8318b8b9dc4 100644 (file)
@@ -1714,7 +1714,7 @@ static void dst_release(struct dvb_frontend *fe)
        struct dst_state *state = fe->demodulator_priv;
        if (state->dst_ca) {
                dvb_unregister_device(state->dst_ca);
-#ifdef CONFIG_DVB_CORE_ATTACH
+#ifdef CONFIG_MEDIA_ATTACH
                symbol_put(dst_ca_attach);
 #endif
        }
diff --git a/drivers/media/dvb/dvb-core/Kconfig b/drivers/media/dvb/dvb-core/Kconfig
deleted file mode 100644 (file)
index e3e6839..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-config DVB_CORE
-       tristate "DVB for Linux"
-       depends on NET && INET
-       select CRC32
-       help
-         Support Digital Video Broadcasting hardware.  Enable this if you
-         own a DVB adapter and want to use it or if you compile Linux for
-         a digital SetTopBox.
-
-         DVB core utility functions for device handling, software fallbacks etc.
-         Say Y when you have a DVB card and want to use it. Say Y if your want
-         to build your drivers outside the kernel, but need the DVB core. All
-         in-kernel drivers will select this automatically if needed.
-
-         API specs and user tools are available from <http://www.linuxtv.org/>.
-
-         Please report problems regarding this driver to the LinuxDVB
-         mailing list.
-
-         If unsure say N.
-
-config DVB_CORE_ATTACH
-       bool "Load and attach frontend modules as needed"
-       depends on DVB_CORE
-       depends on MODULES
-       help
-         Remove the static dependency of DVB card drivers on all
-         frontend modules for all possible card variants. Instead,
-         allow the card drivers to only load the frontend modules
-         they require. This saves several KBytes of memory.
-
-         Note: You will need module-init-tools v3.2 or later for this feature.
-
-         If unsure say Y.
index 2dddd08c5445383cfe1b94352c94bda403147130..8cbdb218952f768fc9128552e64c8a3327370132 100644 (file)
@@ -1189,7 +1189,7 @@ int dvb_unregister_frontend(struct dvb_frontend* fe)
 }
 EXPORT_SYMBOL(dvb_unregister_frontend);
 
-#ifdef CONFIG_DVB_CORE_ATTACH
+#ifdef CONFIG_MEDIA_ATTACH
 void dvb_frontend_detach(struct dvb_frontend* fe)
 {
        void *ptr;
index 5f9a737c6de194065d3e5f7e4de06e0407d8c322..89d12dc477a7b4f4017803a86d1bfaa6ef46b7ce 100644 (file)
@@ -115,7 +115,7 @@ extern int dvb_usercopy(struct inode *inode, struct file *file,
                            unsigned int cmd, void *arg));
 
 /** generic DVB attach function. */
-#ifdef CONFIG_DVB_CORE_ATTACH
+#ifdef CONFIG_MEDIA_ATTACH
 #define dvb_attach(FUNCTION, ARGS...) ({ \
        void *__r = NULL; \
        typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
index 3c8493d2026dd329a9e20c1c6faaf2d9581b94b3..4c1cff9feb2e69ed8e3acc57b536aecc5e5804e1 100644 (file)
@@ -25,7 +25,7 @@ config DVB_USB_A800
        tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)"
        depends on DVB_USB
        select DVB_DIB3000MC
-       select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
        select DVB_PLL if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver.
@@ -35,7 +35,7 @@ config DVB_USB_DIBUSB_MB
        depends on DVB_USB
        select DVB_PLL if !DVB_FE_CUSTOMISE
        select DVB_DIB3000MB
-       select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
        help
          Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by
          DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
@@ -56,7 +56,7 @@ config DVB_USB_DIBUSB_MC
        tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
        depends on DVB_USB
        select DVB_DIB3000MC
-       select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
        help
          Support for USB2.0 DVB-T receivers based on reference designs made by
          DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
@@ -73,8 +73,8 @@ config DVB_USB_DIB0700
        select DVB_DIB7000P
        select DVB_DIB7000M
        select DVB_DIB3000MC
-       select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
-       select DVB_TUNER_MT2266 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE
        select DVB_TUNER_DIB0070
        help
          Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The
@@ -93,7 +93,7 @@ config DVB_USB_UMT_010
        depends on DVB_USB
        select DVB_PLL if !DVB_FE_CUSTOMISE
        select DVB_DIB3000MC
-       select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
 
@@ -105,7 +105,7 @@ config DVB_USB_CXUSB
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
        select DVB_MT352 if !DVB_FE_CUSTOMISE
        select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-       select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the Conexant USB2.0 hybrid reference design.
          Currently, only DVB and ATSC modes are supported, analog mode
@@ -118,7 +118,7 @@ config DVB_USB_M920X
        tristate "Uli m920x DVB-T USB2.0 support"
        depends on DVB_USB
        select DVB_MT352 if !DVB_FE_CUSTOMISE
-       select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver.
          Currently, only devices with a product id of
@@ -129,7 +129,7 @@ config DVB_USB_GL861
        tristate "Genesys Logic GL861 USB2.0 support"
        depends on DVB_USB
        select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-       select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0
          receiver with USB ID 0db0:5581.
@@ -138,7 +138,7 @@ config DVB_USB_AU6610
        tristate "Alcor Micro AU6610 USB2.0 support"
        depends on DVB_USB
        select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-       select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver.
 
@@ -190,7 +190,7 @@ config DVB_USB_NOVA_T_USB2
        tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
        depends on DVB_USB
        select DVB_DIB3000MC
-       select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
        select DVB_PLL if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
@@ -227,8 +227,8 @@ config DVB_USB_OPERA1
 config DVB_USB_AF9005
        tristate "Afatech AF9005 DVB-T USB1.1 support"
        depends on DVB_USB && EXPERIMENTAL
-       select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE
-       select DVB_TUNER_QT1010 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver
          and the TerraTec Cinergy T USB XE (Rev.1)
index 60a910052c16fa0c0488214b5daadd36782e38a5..c6511a6c0ab82dbd9d429d31991c72657ff74a18 100644 (file)
@@ -63,5 +63,5 @@ obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += dvb-usb-af9005-remote.o
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
 # due to tuner-xc3028
-EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
 
index f5fceb3cdb3cb0d71b34e7fa8a1bc272cc04f65e..6d2384605927190abaa5394672fd191fb9a6a6e6 100644 (file)
@@ -15,22 +15,36 @@ config DVB_FE_CUSTOMISE
 comment "DVB-S (satellite) frontends"
        depends on DVB_CORE
 
-config DVB_STV0299
-       tristate "ST STV0299 based"
+config DVB_CX24110
+       tristate "Conexant CX24110 based"
        depends on DVB_CORE && I2C
        default m if DVB_FE_CUSTOMISE
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
-config DVB_CX24110
-       tristate "Conexant CX24110 based"
+config DVB_CX24123
+       tristate "Conexant CX24123 based"
        depends on DVB_CORE && I2C
        default m if DVB_FE_CUSTOMISE
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
-config DVB_CX24123
-       tristate "Conexant CX24123 based"
+config DVB_MT312
+       tristate "Zarlink VP310/MT312 based"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A DVB-S tuner module. Say Y when you want to support this frontend.
+
+config DVB_S5H1420
+       tristate "Samsung S5H1420 based"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A DVB-S tuner module. Say Y when you want to support this frontend.
+
+config DVB_STV0299
+       tristate "ST STV0299 based"
        depends on DVB_CORE && I2C
        default m if DVB_FE_CUSTOMISE
        help
@@ -43,8 +57,8 @@ config DVB_TDA8083
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
-config DVB_MT312
-       tristate "Zarlink VP310/MT312 based"
+config DVB_TDA10086
+       tristate "Philips TDA10086 based"
        depends on DVB_CORE && I2C
        default m if DVB_FE_CUSTOMISE
        help
@@ -57,19 +71,26 @@ config DVB_VES1X93
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
-config DVB_S5H1420
-       tristate "Samsung S5H1420 based"
+config DVB_TUNER_ITD1000
+       tristate "Integrant ITD1000 Zero IF tuner for DVB-S/DSS"
        depends on DVB_CORE && I2C
        default m if DVB_FE_CUSTOMISE
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
-config DVB_TDA10086
-       tristate "Philips TDA10086 based"
+config DVB_TDA826X
+       tristate "Philips TDA826X silicon tuner"
        depends on DVB_CORE && I2C
        default m if DVB_FE_CUSTOMISE
        help
-         A DVB-S tuner module. Say Y when you want to support this frontend.
+         A DVB-S silicon tuner module. Say Y when you want to support this tuner.
+
+config DVB_TUA6100
+       tristate "Infineon TUA6100 PLL"
+       depends on DVB_CORE && I2C
+       default m if DVB_FE_CUSTOMISE
+       help
+         A DVB-S PLL chip.
 
 comment "DVB-T (terrestrial) frontends"
        depends on DVB_CORE
@@ -315,7 +336,7 @@ config DVB_S5H1411
          An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
          to support this frontend.
 
-comment "Tuners/PLL support"
+comment "Digital terrestrial only tuners/PLL"
        depends on DVB_CORE
 
 config DVB_PLL
@@ -326,55 +347,6 @@ config DVB_PLL
          This module drives a number of tuners based on PLL chips with a
          common I2C interface. Say Y when you want to support these tuners.
 
-config DVB_TDA826X
-       tristate "Philips TDA826X silicon tuner"
-       depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
-       help
-         A DVB-S silicon tuner module. Say Y when you want to support this tuner.
-
-config DVB_TDA827X
-       tristate "Philips TDA827X silicon tuner"
-       depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
-       help
-         A DVB-T silicon tuner module. Say Y when you want to support this tuner.
-
-config DVB_TDA18271
-       tristate "NXP TDA18271 silicon tuner"
-       depends on I2C
-       default m if DVB_FE_CUSTOMISE
-       help
-         A silicon tuner module. Say Y when you want to support this tuner.
-
-config DVB_TUNER_QT1010
-       tristate "Quantek QT1010 silicon tuner"
-       depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
-       help
-         A driver for the silicon tuner QT1010 from Quantek.
-
-config DVB_TUNER_MT2060
-       tristate "Microtune MT2060 silicon IF tuner"
-       depends on I2C
-       default m if DVB_FE_CUSTOMISE
-       help
-         A driver for the silicon IF tuner MT2060 from Microtune.
-
-config DVB_TUNER_MT2266
-       tristate "Microtune MT2266 silicon tuner"
-       depends on I2C
-       default m if DVB_FE_CUSTOMISE
-       help
-         A driver for the silicon baseband tuner MT2266 from Microtune.
-
-config DVB_TUNER_MT2131
-       tristate "Microtune MT2131 silicon tuner"
-       depends on I2C
-       default m if DVB_FE_CUSTOMISE
-       help
-         A driver for the silicon baseband tuner MT2131 from Microtune.
-
 config DVB_TUNER_DIB0070
        tristate "DiBcom DiB0070 silicon base-band tuner"
        depends on I2C
@@ -384,21 +356,7 @@ config DVB_TUNER_DIB0070
          This device is only used inside a SiP called togther with a
          demodulator for now.
 
-config DVB_TUNER_XC5000
-       tristate "Xceive XC5000 silicon tuner"
-       depends on I2C
-       default m if DVB_FE_CUSTOMISE
-       help
-         A driver for the silicon tuner XC5000 from Xceive.
-         This device is only used inside a SiP called togther with a
-         demodulator for now.
-
-config DVB_TUNER_ITD1000
-       tristate "Integrant ITD1000 Zero IF tuner for DVB-S/DSS"
-       depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
-
-comment "Miscellaneous devices"
+comment "SEC control devices for DVB-S"
        depends on DVB_CORE
 
 config DVB_LNBP21
@@ -422,11 +380,4 @@ config DVB_ISL6421
        help
          An SEC control chip.
 
-config DVB_TUA6100
-       tristate "TUA6100 PLL"
-       depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
-       help
-         A DVBS PLL chip.
-
 endmenu
index 9747c73dc8269c78c9d8c4e6e7aecbb0a6dded15..a89dc0fc4c6fe90dbb97d5fd22368a66b0c65000 100644 (file)
@@ -3,9 +3,7 @@
 #
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
-EXTRA_CFLAGS += -Idrivers/media/video/
-
-tda18271-objs := tda18271-tables.o tda18271-common.o tda18271-fe.o
+EXTRA_CFLAGS += -Idrivers/media/common/tuners/
 
 obj-$(CONFIG_DVB_PLL) += dvb-pll.o
 obj-$(CONFIG_DVB_STV0299) += stv0299.o
@@ -42,16 +40,9 @@ obj-$(CONFIG_DVB_ISL6405) += isl6405.o
 obj-$(CONFIG_DVB_ISL6421) += isl6421.o
 obj-$(CONFIG_DVB_TDA10086) += tda10086.o
 obj-$(CONFIG_DVB_TDA826X) += tda826x.o
-obj-$(CONFIG_DVB_TDA827X) += tda827x.o
-obj-$(CONFIG_DVB_TDA18271) += tda18271.o
-obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o
-obj-$(CONFIG_DVB_TUNER_MT2266) += mt2266.o
 obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o
-obj-$(CONFIG_DVB_TUNER_QT1010) += qt1010.o
 obj-$(CONFIG_DVB_TUA6100) += tua6100.o
-obj-$(CONFIG_DVB_TUNER_MT2131) += mt2131.o
 obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
-obj-$(CONFIG_DVB_TUNER_XC5000) += xc5000.o
 obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
 obj-$(CONFIG_DVB_AU8522) += au8522.o
 obj-$(CONFIG_DVB_TDA10048) += tda10048.o
index 281e1cb2edc67d516361a4114b8864a7c3c716b6..720ed9ff7c5fda6a43b0b5074e16ee28c487eaf0 100644 (file)
@@ -481,7 +481,7 @@ static void s5h1420_setsymbolrate(struct s5h1420_state* state,
                val *= 2;
        do_div(val, (state->fclk / 1000));
 
-       dprintk("symbol rate register: %06llx\n", val);
+       dprintk("symbol rate register: %06llx\n", (unsigned long long)val);
 
        v = s5h1420_readreg(state, Loop01);
        s5h1420_writereg(state, Loop01, v & 0x7f);
index fe9a4cc141414c18523cb11c1b97dd0138b8c111..fe743aa7f645fb611af3058775ad2b22bbd38081 100644 (file)
@@ -1,3 +1,49 @@
+#
+# Generic video config states
+#
+
+config VIDEO_V4L2
+       tristate
+       depends on VIDEO_DEV && VIDEO_V4L2_COMMON
+       default VIDEO_DEV && VIDEO_V4L2_COMMON
+
+config VIDEO_V4L1
+       tristate
+       depends on VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
+       default VIDEO_DEV && VIDEO_V4L2_COMMON && VIDEO_ALLOW_V4L1
+
+config VIDEOBUF_GEN
+       tristate
+
+config VIDEOBUF_DMA_SG
+       depends on HAS_DMA
+       select VIDEOBUF_GEN
+       tristate
+
+config VIDEOBUF_VMALLOC
+       select VIDEOBUF_GEN
+       tristate
+
+config VIDEOBUF_DVB
+       tristate
+       select VIDEOBUF_GEN
+       select VIDEOBUF_DMA_SG
+
+config VIDEO_BTCX
+       tristate
+
+config VIDEO_IR_I2C
+       tristate
+
+config VIDEO_IR
+       tristate
+       depends on INPUT
+       select VIDEO_IR_I2C if I2C
+
+config VIDEO_TVEEPROM
+       tristate
+       depends on I2C
+
 #
 # Multimedia Video device configuration
 #
@@ -644,7 +690,7 @@ config VIDEO_MXB
        tristate "Siemens-Nixdorf 'Multimedia eXtension Board'"
        depends on PCI && VIDEO_V4L1 && I2C
        select VIDEO_SAA7146_VV
-       select VIDEO_TUNER
+       select MEDIA_TUNER
        select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO
        select VIDEO_TDA9840 if VIDEO_HELPER_CHIPS_AUTO
        select VIDEO_TEA6415C if VIDEO_HELPER_CHIPS_AUTO
@@ -702,6 +748,8 @@ source "drivers/media/video/au0828/Kconfig"
 
 source "drivers/media/video/ivtv/Kconfig"
 
+source "drivers/media/video/cx18/Kconfig"
+
 config VIDEO_M32R_AR
        tristate "AR devices"
        depends on M32R && VIDEO_V4L1
index be14227f37269adb548577df17407aa52c6905ae..a352c6e31f0cbf96496e68d8f6c86e12b7089c0a 100644 (file)
@@ -84,17 +84,7 @@ obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
 obj-$(CONFIG_VIDEO_DPC) += dpc7146.o
 obj-$(CONFIG_TUNER_3036) += tuner-3036.o
 
-obj-$(CONFIG_VIDEO_TUNER) += tuner.o
-
-obj-$(CONFIG_TUNER_XC2028) += tuner-xc2028.o
-obj-$(CONFIG_TUNER_SIMPLE) += tuner-simple.o
-# tuner-types will be merged into tuner-simple, in the future
-obj-$(CONFIG_TUNER_SIMPLE) += tuner-types.o
-obj-$(CONFIG_TUNER_MT20XX) += mt20xx.o
-obj-$(CONFIG_TUNER_TDA8290) += tda8290.o
-obj-$(CONFIG_TUNER_TEA5767) += tea5767.o
-obj-$(CONFIG_TUNER_TEA5761) += tea5761.o
-obj-$(CONFIG_TUNER_TDA9887) += tda9887.o
+obj-$(CONFIG_MEDIA_TUNER) += tuner.o
 
 obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o
 obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o
@@ -134,6 +124,7 @@ obj-$(CONFIG_USB_VICAM)         += usbvideo/
 obj-$(CONFIG_USB_QUICKCAM_MESSENGER)   += usbvideo/
 
 obj-$(CONFIG_VIDEO_IVTV) += ivtv/
+obj-$(CONFIG_VIDEO_CX18) += cx18/
 
 obj-$(CONFIG_VIDEO_VIVI) += vivi.o
 obj-$(CONFIG_VIDEO_CX23885) += cx23885/
@@ -147,3 +138,4 @@ obj-$(CONFIG_VIDEO_AU0828) += au0828/
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
index 41708267e7a4f64a2b5548014eb8f3678871c51f..cab277fafa63a97831567d5c61db98b3d149f574 100644 (file)
@@ -4,7 +4,7 @@ config VIDEO_AU0828
        depends on VIDEO_DEV && I2C && INPUT && DVB_CORE
        select I2C_ALGOBIT
        select DVB_AU8522 if !DVB_FE_CUSTOMIZE
-       select DVB_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
+       select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
        ---help---
          This is a video4linux driver for Auvitek's USB device.
 
index 9f4f572c89c588c55412a0b5f617b098a7b39cae..cd2c58281b4eda4c26ac46483f10208389a881d5 100644 (file)
@@ -2,7 +2,7 @@ au0828-objs     := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o
 
 obj-$(CONFIG_VIDEO_AU0828) += au0828.o
 
-EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
 
index cfc822bb502a92b9cd2c6b66fe3c52d508ec91ef..7431ef6de9f1284f9d475678956fa8fe5ea6c7e1 100644 (file)
@@ -6,7 +6,7 @@ config VIDEO_BT848
        select VIDEO_BTCX
        select VIDEOBUF_DMA_SG
        select VIDEO_IR
-       select VIDEO_TUNER
+       select MEDIA_TUNER
        select VIDEO_TVEEPROM
        select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
        select VIDEO_TVAUDIO if VIDEO_HELPER_CHIPS_AUTO
index 924d216d95705c1bb30dfc562294fb3c69255734..e415f6fc447c5905ffd87ac96e611a1c6bc9cf86 100644 (file)
@@ -9,4 +9,5 @@ bttv-objs      :=      bttv-driver.o bttv-cards.o bttv-if.o \
 obj-$(CONFIG_VIDEO_BT848) += bttv.o
 
 EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
index 03816b73f847560571a1bccd3693bdc5502d1666..27da7b4232754745c0127e61fc39014fe30fa887 100644 (file)
@@ -81,8 +81,6 @@
 /* Limits scaled width, which must be a multiple of 4. */
 #define MAX_HACTIVE (0x3FF & -4)
 
-#define clamp(x, low, high) min (max (low, x), high)
-
 #define BTTV_NORMS    (\
                V4L2_STD_PAL    | V4L2_STD_PAL_N | \
                V4L2_STD_PAL_Nc | V4L2_STD_SECAM | \
index fae469ce16f5da0356bd04705884e536340dbdf5..2a429f9e32cde03068e7ea72a0ddeb93316496e1 100644 (file)
@@ -142,7 +142,8 @@ static int cs5345_command(struct i2c_client *client, unsigned cmd, void *arg)
 
 /* ----------------------------------------------------------------------- */
 
-static int cs5345_probe(struct i2c_client *client)
+static int cs5345_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
 {
        /* Check if the adapter supports the needed features */
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
index f41bfde045fe9dcb667e1373ac6e8424599db459..2dfd0afc62db2a72f29c180e11a291646049a3be 100644 (file)
@@ -135,7 +135,8 @@ static int cs53l32a_command(struct i2c_client *client, unsigned cmd, void *arg)
  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  */
 
-static int cs53l32a_probe(struct i2c_client *client)
+static int cs53l32a_probe(struct i2c_client *client,
+                         const struct i2c_device_id *id)
 {
        int i;
 
diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig
new file mode 100644 (file)
index 0000000..acc4b47
--- /dev/null
@@ -0,0 +1,20 @@
+config VIDEO_CX18
+       tristate "Conexant cx23418 MPEG encoder support"
+       depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL
+       select I2C_ALGOBIT
+       select FW_LOADER
+       select VIDEO_IR
+       select MEDIA_TUNER
+       select VIDEO_TVEEPROM
+       select VIDEO_CX2341X
+       select VIDEO_CS5345
+       select DVB_S5H1409
+       ---help---
+         This is a video4linux driver for Conexant cx23418 based
+         PCI combo video recorder devices.
+
+         This is used in devices such as the Hauppauge HVR-1600
+         cards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cx18.
diff --git a/drivers/media/video/cx18/Makefile b/drivers/media/video/cx18/Makefile
new file mode 100644 (file)
index 0000000..b23d2e2
--- /dev/null
@@ -0,0 +1,11 @@
+cx18-objs    := cx18-driver.o cx18-cards.o cx18-i2c.o cx18-firmware.o cx18-gpio.o \
+       cx18-queue.o cx18-streams.o cx18-fileops.o cx18-ioctl.o cx18-controls.o \
+       cx18-mailbox.o cx18-vbi.o cx18-audio.o cx18-video.o cx18-irq.o \
+       cx18-av-core.o cx18-av-audio.o cx18-av-firmware.o cx18-av-vbi.o cx18-scb.o \
+       cx18-dvb.o
+
+obj-$(CONFIG_VIDEO_CX18) += cx18.o
+
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
diff --git a/drivers/media/video/cx18/cx18-audio.c b/drivers/media/video/cx18/cx18-audio.c
new file mode 100644 (file)
index 0000000..1adc404
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ *  cx18 audio-related functions
+ *
+ *  Derived from ivtv-audio.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 "cx18-driver.h"
+#include "cx18-i2c.h"
+#include "cx18-cards.h"
+#include "cx18-audio.h"
+
+/* Selects the audio input and output according to the current
+   settings. */
+int cx18_audio_set_io(struct cx18 *cx)
+{
+       struct v4l2_routing route;
+       u32 audio_input;
+       int mux_input;
+
+       /* Determine which input to use */
+       if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
+               audio_input = cx->card->radio_input.audio_input;
+               mux_input = cx->card->radio_input.muxer_input;
+       } else {
+               audio_input =
+                       cx->card->audio_inputs[cx->audio_input].audio_input;
+               mux_input =
+                       cx->card->audio_inputs[cx->audio_input].muxer_input;
+       }
+
+       /* handle muxer chips */
+       route.input = mux_input;
+       route.output = 0;
+       cx18_i2c_hw(cx, cx->card->hw_muxer, VIDIOC_INT_S_AUDIO_ROUTING, &route);
+
+       route.input = audio_input;
+       return cx18_i2c_hw(cx, cx->card->hw_audio_ctrl,
+                       VIDIOC_INT_S_AUDIO_ROUTING, &route);
+}
+
+void cx18_audio_set_route(struct cx18 *cx, struct v4l2_routing *route)
+{
+       cx18_i2c_hw(cx, cx->card->hw_audio_ctrl,
+                       VIDIOC_INT_S_AUDIO_ROUTING, route);
+}
+
+void cx18_audio_set_audio_clock_freq(struct cx18 *cx, u8 freq)
+{
+       static u32 freqs[3] = { 44100, 48000, 32000 };
+
+       /* The audio clock of the digitizer must match the codec sample
+          rate otherwise you get some very strange effects. */
+       if (freq > 2)
+               return;
+       cx18_call_i2c_clients(cx, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freqs[freq]);
+}
diff --git a/drivers/media/video/cx18/cx18-audio.h b/drivers/media/video/cx18/cx18-audio.h
new file mode 100644 (file)
index 0000000..cb569a6
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ *  cx18 audio-related functions
+ *
+ *  Derived from ivtv-audio.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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
+ */
+
+int cx18_audio_set_io(struct cx18 *cx);
+void cx18_audio_set_route(struct cx18 *cx, struct v4l2_routing *route);
+void cx18_audio_set_audio_clock_freq(struct cx18 *cx, u8 freq);
diff --git a/drivers/media/video/cx18/cx18-av-audio.c b/drivers/media/video/cx18/cx18-av-audio.c
new file mode 100644 (file)
index 0000000..2dc3a5d
--- /dev/null
@@ -0,0 +1,361 @@
+/*
+ *  cx18 ADEC audio functions
+ *
+ *  Derived from cx25840-audio.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+#include "cx18-driver.h"
+
+static int set_audclk_freq(struct cx18 *cx, u32 freq)
+{
+       struct cx18_av_state *state = &cx->av_state;
+
+       if (freq != 32000 && freq != 44100 && freq != 48000)
+               return -EINVAL;
+
+       /* common for all inputs and rates */
+       /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */
+       cx18_av_write(cx, 0x127, 0x50);
+
+       if (state->aud_input != CX18_AV_AUDIO_SERIAL) {
+               switch (freq) {
+               case 32000:
+                       /* VID_PLL and AUX_PLL */
+                       cx18_av_write4(cx, 0x108, 0x1006040f);
+
+                       /* AUX_PLL_FRAC */
+                       cx18_av_write4(cx, 0x110, 0x01bb39ee);
+
+                       /* src3/4/6_ctl = 0x0801f77f */
+                       cx18_av_write4(cx, 0x900, 0x0801f77f);
+                       cx18_av_write4(cx, 0x904, 0x0801f77f);
+                       cx18_av_write4(cx, 0x90c, 0x0801f77f);
+                       break;
+
+               case 44100:
+                       /* VID_PLL and AUX_PLL */
+                       cx18_av_write4(cx, 0x108, 0x1009040f);
+
+                       /* AUX_PLL_FRAC */
+                       cx18_av_write4(cx, 0x110, 0x00ec6bd6);
+
+                       /* src3/4/6_ctl = 0x08016d59 */
+                       cx18_av_write4(cx, 0x900, 0x08016d59);
+                       cx18_av_write4(cx, 0x904, 0x08016d59);
+                       cx18_av_write4(cx, 0x90c, 0x08016d59);
+                       break;
+
+               case 48000:
+                       /* VID_PLL and AUX_PLL */
+                       cx18_av_write4(cx, 0x108, 0x100a040f);
+
+                       /* AUX_PLL_FRAC */
+                       cx18_av_write4(cx, 0x110, 0x0098d6e5);
+
+                       /* src3/4/6_ctl = 0x08014faa */
+                       cx18_av_write4(cx, 0x900, 0x08014faa);
+                       cx18_av_write4(cx, 0x904, 0x08014faa);
+                       cx18_av_write4(cx, 0x90c, 0x08014faa);
+                       break;
+               }
+       } else {
+               switch (freq) {
+               case 32000:
+                       /* VID_PLL and AUX_PLL */
+                       cx18_av_write4(cx, 0x108, 0x1e08040f);
+
+                       /* AUX_PLL_FRAC */
+                       cx18_av_write4(cx, 0x110, 0x012a0869);
+
+                       /* src1_ctl = 0x08010000 */
+                       cx18_av_write4(cx, 0x8f8, 0x08010000);
+
+                       /* src3/4/6_ctl = 0x08020000 */
+                       cx18_av_write4(cx, 0x900, 0x08020000);
+                       cx18_av_write4(cx, 0x904, 0x08020000);
+                       cx18_av_write4(cx, 0x90c, 0x08020000);
+
+                       /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x14 */
+                       cx18_av_write(cx, 0x127, 0x54);
+                       break;
+
+               case 44100:
+                       /* VID_PLL and AUX_PLL */
+                       cx18_av_write4(cx, 0x108, 0x1809040f);
+
+                       /* AUX_PLL_FRAC */
+                       cx18_av_write4(cx, 0x110, 0x00ec6bd6);
+
+                       /* src1_ctl = 0x08010000 */
+                       cx18_av_write4(cx, 0x8f8, 0x080160cd);
+
+                       /* src3/4/6_ctl = 0x08020000 */
+                       cx18_av_write4(cx, 0x900, 0x08017385);
+                       cx18_av_write4(cx, 0x904, 0x08017385);
+                       cx18_av_write4(cx, 0x90c, 0x08017385);
+                       break;
+
+               case 48000:
+                       /* VID_PLL and AUX_PLL */
+                       cx18_av_write4(cx, 0x108, 0x180a040f);
+
+                       /* AUX_PLL_FRAC */
+                       cx18_av_write4(cx, 0x110, 0x0098d6e5);
+
+                       /* src1_ctl = 0x08010000 */
+                       cx18_av_write4(cx, 0x8f8, 0x08018000);
+
+                       /* src3/4/6_ctl = 0x08020000 */
+                       cx18_av_write4(cx, 0x900, 0x08015555);
+                       cx18_av_write4(cx, 0x904, 0x08015555);
+                       cx18_av_write4(cx, 0x90c, 0x08015555);
+                       break;
+               }
+       }
+
+       state->audclk_freq = freq;
+
+       return 0;
+}
+
+void cx18_av_audio_set_path(struct cx18 *cx)
+{
+       struct cx18_av_state *state = &cx->av_state;
+
+       /* stop microcontroller */
+       cx18_av_and_or(cx, 0x803, ~0x10, 0);
+
+       /* assert soft reset */
+       cx18_av_and_or(cx, 0x810, ~0x1, 0x01);
+
+       /* Mute everything to prevent the PFFT! */
+       cx18_av_write(cx, 0x8d3, 0x1f);
+
+       if (state->aud_input == CX18_AV_AUDIO_SERIAL) {
+               /* Set Path1 to Serial Audio Input */
+               cx18_av_write4(cx, 0x8d0, 0x01011012);
+
+               /* The microcontroller should not be started for the
+                * non-tuner inputs: autodetection is specific for
+                * TV audio. */
+       } else {
+               /* Set Path1 to Analog Demod Main Channel */
+               cx18_av_write4(cx, 0x8d0, 0x1f063870);
+       }
+
+       set_audclk_freq(cx, state->audclk_freq);
+
+       /* deassert soft reset */
+       cx18_av_and_or(cx, 0x810, ~0x1, 0x00);
+
+       if (state->aud_input != CX18_AV_AUDIO_SERIAL) {
+               /* When the microcontroller detects the
+                * audio format, it will unmute the lines */
+               cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
+       }
+}
+
+static int get_volume(struct cx18 *cx)
+{
+       /* Volume runs +18dB to -96dB in 1/2dB steps
+        * change to fit the msp3400 -114dB to +12dB range */
+
+       /* check PATH1_VOLUME */
+       int vol = 228 - cx18_av_read(cx, 0x8d4);
+       vol = (vol / 2) + 23;
+       return vol << 9;
+}
+
+static void set_volume(struct cx18 *cx, int volume)
+{
+       /* First convert the volume to msp3400 values (0-127) */
+       int vol = volume >> 9;
+       /* now scale it up to cx18_av values
+        * -114dB to -96dB maps to 0
+        * this should be 19, but in my testing that was 4dB too loud */
+       if (vol <= 23)
+               vol = 0;
+       else
+               vol -= 23;
+
+       /* PATH1_VOLUME */
+       cx18_av_write(cx, 0x8d4, 228 - (vol * 2));
+}
+
+static int get_bass(struct cx18 *cx)
+{
+       /* bass is 49 steps +12dB to -12dB */
+
+       /* check PATH1_EQ_BASS_VOL */
+       int bass = cx18_av_read(cx, 0x8d9) & 0x3f;
+       bass = (((48 - bass) * 0xffff) + 47) / 48;
+       return bass;
+}
+
+static void set_bass(struct cx18 *cx, int bass)
+{
+       /* PATH1_EQ_BASS_VOL */
+       cx18_av_and_or(cx, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
+}
+
+static int get_treble(struct cx18 *cx)
+{
+       /* treble is 49 steps +12dB to -12dB */
+
+       /* check PATH1_EQ_TREBLE_VOL */
+       int treble = cx18_av_read(cx, 0x8db) & 0x3f;
+       treble = (((48 - treble) * 0xffff) + 47) / 48;
+       return treble;
+}
+
+static void set_treble(struct cx18 *cx, int treble)
+{
+       /* PATH1_EQ_TREBLE_VOL */
+       cx18_av_and_or(cx, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
+}
+
+static int get_balance(struct cx18 *cx)
+{
+       /* balance is 7 bit, 0 to -96dB */
+
+       /* check PATH1_BAL_LEVEL */
+       int balance = cx18_av_read(cx, 0x8d5) & 0x7f;
+       /* check PATH1_BAL_LEFT */
+       if ((cx18_av_read(cx, 0x8d5) & 0x80) == 0)
+               balance = 0x80 - balance;
+       else
+               balance = 0x80 + balance;
+       return balance << 8;
+}
+
+static void set_balance(struct cx18 *cx, int balance)
+{
+       int bal = balance >> 8;
+       if (bal > 0x80) {
+               /* PATH1_BAL_LEFT */
+               cx18_av_and_or(cx, 0x8d5, 0x7f, 0x80);
+               /* PATH1_BAL_LEVEL */
+               cx18_av_and_or(cx, 0x8d5, ~0x7f, bal & 0x7f);
+       } else {
+               /* PATH1_BAL_LEFT */
+               cx18_av_and_or(cx, 0x8d5, 0x7f, 0x00);
+               /* PATH1_BAL_LEVEL */
+               cx18_av_and_or(cx, 0x8d5, ~0x7f, 0x80 - bal);
+       }
+}
+
+static int get_mute(struct cx18 *cx)
+{
+       /* check SRC1_MUTE_EN */
+       return cx18_av_read(cx, 0x8d3) & 0x2 ? 1 : 0;
+}
+
+static void set_mute(struct cx18 *cx, int mute)
+{
+       struct cx18_av_state *state = &cx->av_state;
+
+       if (state->aud_input != CX18_AV_AUDIO_SERIAL) {
+               /* Must turn off microcontroller in order to mute sound.
+                * Not sure if this is the best method, but it does work.
+                * If the microcontroller is running, then it will undo any
+                * changes to the mute register. */
+               if (mute) {
+                       /* disable microcontroller */
+                       cx18_av_and_or(cx, 0x803, ~0x10, 0x00);
+                       cx18_av_write(cx, 0x8d3, 0x1f);
+               } else {
+                       /* enable microcontroller */
+                       cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
+               }
+       } else {
+               /* SRC1_MUTE_EN */
+               cx18_av_and_or(cx, 0x8d3, ~0x2, mute ? 0x02 : 0x00);
+       }
+}
+
+int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg)
+{
+       struct cx18_av_state *state = &cx->av_state;
+       struct v4l2_control *ctrl = arg;
+       int retval;
+
+       switch (cmd) {
+       case VIDIOC_INT_AUDIO_CLOCK_FREQ:
+               if (state->aud_input != CX18_AV_AUDIO_SERIAL) {
+                       cx18_av_and_or(cx, 0x803, ~0x10, 0);
+                       cx18_av_write(cx, 0x8d3, 0x1f);
+               }
+               cx18_av_and_or(cx, 0x810, ~0x1, 1);
+               retval = set_audclk_freq(cx, *(u32 *)arg);
+               cx18_av_and_or(cx, 0x810, ~0x1, 0);
+               if (state->aud_input != CX18_AV_AUDIO_SERIAL)
+                       cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
+               return retval;
+
+       case VIDIOC_G_CTRL:
+               switch (ctrl->id) {
+               case V4L2_CID_AUDIO_VOLUME:
+                       ctrl->value = get_volume(cx);
+                       break;
+               case V4L2_CID_AUDIO_BASS:
+                       ctrl->value = get_bass(cx);
+                       break;
+               case V4L2_CID_AUDIO_TREBLE:
+                       ctrl->value = get_treble(cx);
+                       break;
+               case V4L2_CID_AUDIO_BALANCE:
+                       ctrl->value = get_balance(cx);
+                       break;
+               case V4L2_CID_AUDIO_MUTE:
+                       ctrl->value = get_mute(cx);
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+
+       case VIDIOC_S_CTRL:
+               switch (ctrl->id) {
+               case V4L2_CID_AUDIO_VOLUME:
+                       set_volume(cx, ctrl->value);
+                       break;
+               case V4L2_CID_AUDIO_BASS:
+                       set_bass(cx, ctrl->value);
+                       break;
+               case V4L2_CID_AUDIO_TREBLE:
+                       set_treble(cx, ctrl->value);
+                       break;
+               case V4L2_CID_AUDIO_BALANCE:
+                       set_balance(cx, ctrl->value);
+                       break;
+               case V4L2_CID_AUDIO_MUTE:
+                       set_mute(cx, ctrl->value);
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c
new file mode 100644 (file)
index 0000000..6686490
--- /dev/null
@@ -0,0 +1,879 @@
+/*
+ *  cx18 ADEC audio functions
+ *
+ *  Derived from cx25840-core.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+#include "cx18-driver.h"
+
+int cx18_av_write(struct cx18 *cx, u16 addr, u8 value)
+{
+       u32 x = readl(cx->reg_mem + 0xc40000 + (addr & ~3));
+       u32 mask = 0xff;
+       int shift = (addr & 3) * 8;
+
+       x = (x & ~(mask << shift)) | ((u32)value << shift);
+       writel(x, cx->reg_mem + 0xc40000 + (addr & ~3));
+       return 0;
+}
+
+int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value)
+{
+       writel(value, cx->reg_mem + 0xc40000 + addr);
+       return 0;
+}
+
+u8 cx18_av_read(struct cx18 *cx, u16 addr)
+{
+       u32 x = readl(cx->reg_mem + 0xc40000 + (addr & ~3));
+       int shift = (addr & 3) * 8;
+
+       return (x >> shift) & 0xff;
+}
+
+u32 cx18_av_read4(struct cx18 *cx, u16 addr)
+{
+       return readl(cx->reg_mem + 0xc40000 + addr);
+}
+
+int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned and_mask,
+                  u8 or_value)
+{
+       return cx18_av_write(cx, addr,
+                            (cx18_av_read(cx, addr) & and_mask) |
+                            or_value);
+}
+
+int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 and_mask,
+                  u32 or_value)
+{
+       return cx18_av_write4(cx, addr,
+                            (cx18_av_read4(cx, addr) & and_mask) |
+                            or_value);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
+                                       enum cx18_av_audio_input aud_input);
+static void log_audio_status(struct cx18 *cx);
+static void log_video_status(struct cx18 *cx);
+
+/* ----------------------------------------------------------------------- */
+
+static void cx18_av_initialize(struct cx18 *cx)
+{
+       u32 v;
+
+       cx18_av_loadfw(cx);
+       /* Stop 8051 code execution */
+       cx18_av_write4(cx, CXADEC_DL_CTL, 0x03000000);
+
+       /* initallize the PLL by toggling sleep bit */
+       v = cx18_av_read4(cx, CXADEC_HOST_REG1);
+       /* enable sleep mode */
+       cx18_av_write4(cx, CXADEC_HOST_REG1, v | 1);
+       /* disable sleep mode */
+       cx18_av_write4(cx, CXADEC_HOST_REG1, v & 0xfffe);
+
+       /* initialize DLLs */
+       v = cx18_av_read4(cx, CXADEC_DLL1_DIAG_CTRL) & 0xE1FFFEFF;
+       /* disable FLD */
+       cx18_av_write4(cx, CXADEC_DLL1_DIAG_CTRL, v);
+       /* enable FLD */
+       cx18_av_write4(cx, CXADEC_DLL1_DIAG_CTRL, v | 0x10000100);
+
+       v = cx18_av_read4(cx, CXADEC_DLL2_DIAG_CTRL) & 0xE1FFFEFF;
+       /* disable FLD */
+       cx18_av_write4(cx, CXADEC_DLL2_DIAG_CTRL, v);
+       /* enable FLD */
+       cx18_av_write4(cx, CXADEC_DLL2_DIAG_CTRL, v | 0x06000100);
+
+       /* set analog bias currents. Set Vreg to 1.20V. */
+       cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL1, 0x000A1802);
+
+       v = cx18_av_read4(cx, CXADEC_AFE_DIAG_CTRL3) | 1;
+       /* enable TUNE_FIL_RST */
+       cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL3, v);
+       /* disable TUNE_FIL_RST */
+       cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL3, v & 0xFFFFFFFE);
+
+       /* enable 656 output */
+       cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x040C00);
+
+       /* video output drive strength */
+       cx18_av_and_or4(cx, CXADEC_PIN_CTRL2, ~0, 0x2);
+
+       /* reset video */
+       cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0x8000);
+       cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0);
+
+       /* set video to auto-detect */
+       /* Clear bits 11-12 to enable slow locking mode.  Set autodetect mode */
+       /* set the comb notch = 1 */
+       cx18_av_and_or4(cx, CXADEC_MODE_CTRL, 0xFFF7E7F0, 0x02040800);
+
+       /* Enable wtw_en in CRUSH_CTRL (Set bit 22) */
+       /* Enable maj_sel in CRUSH_CTRL (Set bit 20) */
+       cx18_av_and_or4(cx, CXADEC_CRUSH_CTRL, ~0, 0x00500000);
+
+       /* Set VGA_TRACK_RANGE to 0x20 */
+       cx18_av_and_or4(cx, CXADEC_DFE_CTRL2, 0xFFFF00FF, 0x00002000);
+
+       /* Enable VBI capture */
+       cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010253F);
+       /* cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4010253E); */
+
+       /* Set the video input.
+          The setting in MODE_CTRL gets lost when we do the above setup */
+       /* EncSetSignalStd(dwDevNum, pEnc->dwSigStd); */
+       /* EncSetVideoInput(dwDevNum, pEnc->VidIndSelection); */
+
+       v = cx18_av_read4(cx, CXADEC_AFE_CTRL);
+       v &= 0xFFFBFFFF;            /* turn OFF bit 18 for droop_comp_ch1 */
+       v &= 0xFFFF7FFF;            /* turn OFF bit 9 for clamp_sel_ch1 */
+       v &= 0xFFFFFFFE;            /* turn OFF bit 0 for 12db_ch1 */
+       /* v |= 0x00000001;*/            /* turn ON bit 0 for 12db_ch1 */
+       cx18_av_write4(cx, CXADEC_AFE_CTRL, v);
+
+/*     if(dwEnable && dw3DCombAvailable) { */
+/*             CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x7728021F); */
+/*    } else { */
+/*             CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x6628021F); */
+/*    } */
+       cx18_av_write4(cx, CXADEC_SRC_COMB_CFG, 0x6628021F);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void input_change(struct cx18 *cx)
+{
+       struct cx18_av_state *state = &cx->av_state;
+       v4l2_std_id std = state->std;
+
+       /* Follow step 8c and 8d of section 3.16 in the cx18_av datasheet */
+       if (std & V4L2_STD_SECAM)
+               cx18_av_write(cx, 0x402, 0);
+       else {
+               cx18_av_write(cx, 0x402, 0x04);
+               cx18_av_write(cx, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11);
+       }
+       cx18_av_and_or(cx, 0x401, ~0x60, 0);
+       cx18_av_and_or(cx, 0x401, ~0x60, 0x60);
+
+       if (std & V4L2_STD_525_60) {
+               if (std == V4L2_STD_NTSC_M_JP) {
+                       /* Japan uses EIAJ audio standard */
+                       cx18_av_write(cx, 0x808, 0xf7);
+               } else if (std == V4L2_STD_NTSC_M_KR) {
+                       /* South Korea uses A2 audio standard */
+                       cx18_av_write(cx, 0x808, 0xf8);
+               } else {
+                       /* Others use the BTSC audio standard */
+                       cx18_av_write(cx, 0x808, 0xf6);
+               }
+               cx18_av_write(cx, 0x80b, 0x00);
+       } else if (std & V4L2_STD_PAL) {
+               /* Follow tuner change procedure for PAL */
+               cx18_av_write(cx, 0x808, 0xff);
+               cx18_av_write(cx, 0x80b, 0x03);
+       } else if (std & V4L2_STD_SECAM) {
+               /* Select autodetect for SECAM */
+               cx18_av_write(cx, 0x808, 0xff);
+               cx18_av_write(cx, 0x80b, 0x03);
+       }
+
+       if (cx18_av_read(cx, 0x803) & 0x10) {
+               /* restart audio decoder microcontroller */
+               cx18_av_and_or(cx, 0x803, ~0x10, 0x00);
+               cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
+       }
+}
+
+static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
+                                       enum cx18_av_audio_input aud_input)
+{
+       struct cx18_av_state *state = &cx->av_state;
+       u8 is_composite = (vid_input >= CX18_AV_COMPOSITE1 &&
+                          vid_input <= CX18_AV_COMPOSITE8);
+       u8 reg;
+
+       CX18_DEBUG_INFO("decoder set video input %d, audio input %d\n",
+                       vid_input, aud_input);
+
+       if (is_composite) {
+               reg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1);
+       } else {
+               int luma = vid_input & 0xf0;
+               int chroma = vid_input & 0xf00;
+
+               if ((vid_input & ~0xff0) ||
+                   luma < CX18_AV_SVIDEO_LUMA1 ||
+                   luma > CX18_AV_SVIDEO_LUMA4 ||
+                   chroma < CX18_AV_SVIDEO_CHROMA4 ||
+                   chroma > CX18_AV_SVIDEO_CHROMA8) {
+                       CX18_ERR("0x%04x is not a valid video input!\n",
+                                       vid_input);
+                       return -EINVAL;
+               }
+               reg = 0xf0 + ((luma - CX18_AV_SVIDEO_LUMA1) >> 4);
+               if (chroma >= CX18_AV_SVIDEO_CHROMA7) {
+                       reg &= 0x3f;
+                       reg |= (chroma - CX18_AV_SVIDEO_CHROMA7) >> 2;
+               } else {
+                       reg &= 0xcf;
+                       reg |= (chroma - CX18_AV_SVIDEO_CHROMA4) >> 4;
+               }
+       }
+
+       switch (aud_input) {
+       case CX18_AV_AUDIO_SERIAL:
+               /* do nothing, use serial audio input */
+               break;
+       case CX18_AV_AUDIO4: reg &= ~0x30; break;
+       case CX18_AV_AUDIO5: reg &= ~0x30; reg |= 0x10; break;
+       case CX18_AV_AUDIO6: reg &= ~0x30; reg |= 0x20; break;
+       case CX18_AV_AUDIO7: reg &= ~0xc0; break;
+       case CX18_AV_AUDIO8: reg &= ~0xc0; reg |= 0x40; break;
+
+       default:
+               CX18_ERR("0x%04x is not a valid audio input!\n", aud_input);
+               return -EINVAL;
+       }
+
+       cx18_av_write(cx, 0x103, reg);
+       /* Set INPUT_MODE to Composite (0) or S-Video (1) */
+       cx18_av_and_or(cx, 0x401, ~0x6, is_composite ? 0 : 0x02);
+       /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
+       cx18_av_and_or(cx, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0);
+       /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */
+       if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30)
+               cx18_av_and_or(cx, 0x102, ~0x4, 4);
+       else
+               cx18_av_and_or(cx, 0x102, ~0x4, 0);
+       /*cx18_av_and_or4(cx, 0x104, ~0x001b4180, 0x00004180);*/
+
+       state->vid_input = vid_input;
+       state->aud_input = aud_input;
+       cx18_av_audio_set_path(cx);
+       input_change(cx);
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int set_v4lstd(struct cx18 *cx)
+{
+       struct cx18_av_state *state = &cx->av_state;
+       u8 fmt = 0;     /* zero is autodetect */
+       u8 pal_m = 0;
+
+       /* First tests should be against specific std */
+       if (state->std == V4L2_STD_NTSC_M_JP) {
+               fmt = 0x2;
+       } else if (state->std == V4L2_STD_NTSC_443) {
+               fmt = 0x3;
+       } else if (state->std == V4L2_STD_PAL_M) {
+               pal_m = 1;
+               fmt = 0x5;
+       } else if (state->std == V4L2_STD_PAL_N) {
+               fmt = 0x6;
+       } else if (state->std == V4L2_STD_PAL_Nc) {
+               fmt = 0x7;
+       } else if (state->std == V4L2_STD_PAL_60) {
+               fmt = 0x8;
+       } else {
+               /* Then, test against generic ones */
+               if (state->std & V4L2_STD_NTSC)
+                       fmt = 0x1;
+               else if (state->std & V4L2_STD_PAL)
+                       fmt = 0x4;
+               else if (state->std & V4L2_STD_SECAM)
+                       fmt = 0xc;
+       }
+
+       CX18_DEBUG_INFO("changing video std to fmt %i\n", fmt);
+
+       /* Follow step 9 of section 3.16 in the cx18_av datasheet.
+          Without this PAL may display a vertical ghosting effect.
+          This happens for example with the Yuan MPC622. */
+       if (fmt >= 4 && fmt < 8) {
+               /* Set format to NTSC-M */
+               cx18_av_and_or(cx, 0x400, ~0xf, 1);
+               /* Turn off LCOMB */
+               cx18_av_and_or(cx, 0x47b, ~6, 0);
+       }
+       cx18_av_and_or(cx, 0x400, ~0xf, fmt);
+       cx18_av_and_or(cx, 0x403, ~0x3, pal_m);
+       cx18_av_vbi_setup(cx);
+       input_change(cx);
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int set_v4lctrl(struct cx18 *cx, struct v4l2_control *ctrl)
+{
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               if (ctrl->value < 0 || ctrl->value > 255) {
+                       CX18_ERR("invalid brightness setting %d\n",
+                                   ctrl->value);
+                       return -ERANGE;
+               }
+
+               cx18_av_write(cx, 0x414, ctrl->value - 128);
+               break;
+
+       case V4L2_CID_CONTRAST:
+               if (ctrl->value < 0 || ctrl->value > 127) {
+                       CX18_ERR("invalid contrast setting %d\n",
+                                   ctrl->value);
+                       return -ERANGE;
+               }
+
+               cx18_av_write(cx, 0x415, ctrl->value << 1);
+               break;
+
+       case V4L2_CID_SATURATION:
+               if (ctrl->value < 0 || ctrl->value > 127) {
+                       CX18_ERR("invalid saturation setting %d\n",
+                                   ctrl->value);
+                       return -ERANGE;
+               }
+
+               cx18_av_write(cx, 0x420, ctrl->value << 1);
+               cx18_av_write(cx, 0x421, ctrl->value << 1);
+               break;
+
+       case V4L2_CID_HUE:
+               if (ctrl->value < -127 || ctrl->value > 127) {
+                       CX18_ERR("invalid hue setting %d\n", ctrl->value);
+                       return -ERANGE;
+               }
+
+               cx18_av_write(cx, 0x422, ctrl->value);
+               break;
+
+       case V4L2_CID_AUDIO_VOLUME:
+       case V4L2_CID_AUDIO_BASS:
+       case V4L2_CID_AUDIO_TREBLE:
+       case V4L2_CID_AUDIO_BALANCE:
+       case V4L2_CID_AUDIO_MUTE:
+               return cx18_av_audio(cx, VIDIOC_S_CTRL, ctrl);
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int get_v4lctrl(struct cx18 *cx, struct v4l2_control *ctrl)
+{
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               ctrl->value = (s8)cx18_av_read(cx, 0x414) + 128;
+               break;
+       case V4L2_CID_CONTRAST:
+               ctrl->value = cx18_av_read(cx, 0x415) >> 1;
+               break;
+       case V4L2_CID_SATURATION:
+               ctrl->value = cx18_av_read(cx, 0x420) >> 1;
+               break;
+       case V4L2_CID_HUE:
+               ctrl->value = (s8)cx18_av_read(cx, 0x422);
+               break;
+       case V4L2_CID_AUDIO_VOLUME:
+       case V4L2_CID_AUDIO_BASS:
+       case V4L2_CID_AUDIO_TREBLE:
+       case V4L2_CID_AUDIO_BALANCE:
+       case V4L2_CID_AUDIO_MUTE:
+               return cx18_av_audio(cx, VIDIOC_G_CTRL, ctrl);
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int get_v4lfmt(struct cx18 *cx, struct v4l2_format *fmt)
+{
+       switch (fmt->type) {
+       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+               return cx18_av_vbi(cx, VIDIOC_G_FMT, fmt);
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int set_v4lfmt(struct cx18 *cx, struct v4l2_format *fmt)
+{
+       struct cx18_av_state *state = &cx->av_state;
+       struct v4l2_pix_format *pix;
+       int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
+       int is_50Hz = !(state->std & V4L2_STD_525_60);
+
+       switch (fmt->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               pix = &(fmt->fmt.pix);
+
+               Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4;
+               Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4;
+
+               Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4;
+               Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4;
+
+               Vlines = pix->height + (is_50Hz ? 4 : 7);
+
+               if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) ||
+                   (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
+                       CX18_ERR("%dx%d is not a valid size!\n",
+                                   pix->width, pix->height);
+                       return -ERANGE;
+               }
+
+               HSC = (Hsrc * (1 << 20)) / pix->width - (1 << 20);
+               VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
+               VSC &= 0x1fff;
+
+               if (pix->width >= 385)
+                       filter = 0;
+               else if (pix->width > 192)
+                       filter = 1;
+               else if (pix->width > 96)
+                       filter = 2;
+               else
+                       filter = 3;
+
+               CX18_DEBUG_INFO("decoder set size %dx%d -> scale  %ux%u\n",
+                           pix->width, pix->height, HSC, VSC);
+
+               /* HSCALE=HSC */
+               cx18_av_write(cx, 0x418, HSC & 0xff);
+               cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff);
+               cx18_av_write(cx, 0x41a, HSC >> 16);
+               /* VSCALE=VSC */
+               cx18_av_write(cx, 0x41c, VSC & 0xff);
+               cx18_av_write(cx, 0x41d, VSC >> 8);
+               /* VS_INTRLACE=1 VFILT=filter */
+               cx18_av_write(cx, 0x41e, 0x8 | filter);
+               break;
+
+       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+               return cx18_av_vbi(cx, VIDIOC_S_FMT, fmt);
+
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+               return cx18_av_vbi(cx, VIDIOC_S_FMT, fmt);
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg)
+{
+       struct cx18_av_state *state = &cx->av_state;
+       struct v4l2_tuner *vt = arg;
+       struct v4l2_routing *route = arg;
+
+       /* ignore these commands */
+       switch (cmd) {
+       case TUNER_SET_TYPE_ADDR:
+               return 0;
+       }
+
+       if (!state->is_initialized) {
+               CX18_DEBUG_INFO("cmd %08x triggered fw load\n", cmd);
+               /* initialize on first use */
+               state->is_initialized = 1;
+               cx18_av_initialize(cx);
+       }
+
+       switch (cmd) {
+       case VIDIOC_INT_DECODE_VBI_LINE:
+               return cx18_av_vbi(cx, cmd, arg);
+
+       case VIDIOC_INT_AUDIO_CLOCK_FREQ:
+               return cx18_av_audio(cx, cmd, arg);
+
+       case VIDIOC_STREAMON:
+               CX18_DEBUG_INFO("enable output\n");
+               cx18_av_write(cx, 0x115, 0x8c);
+               cx18_av_write(cx, 0x116, 0x07);
+               break;
+
+       case VIDIOC_STREAMOFF:
+               CX18_DEBUG_INFO("disable output\n");
+               cx18_av_write(cx, 0x115, 0x00);
+               cx18_av_write(cx, 0x116, 0x00);
+               break;
+
+       case VIDIOC_LOG_STATUS:
+               log_video_status(cx);
+               log_audio_status(cx);
+               break;
+
+       case VIDIOC_G_CTRL:
+               return get_v4lctrl(cx, (struct v4l2_control *)arg);
+
+       case VIDIOC_S_CTRL:
+               return set_v4lctrl(cx, (struct v4l2_control *)arg);
+
+       case VIDIOC_QUERYCTRL:
+       {
+               struct v4l2_queryctrl *qc = arg;
+
+               switch (qc->id) {
+               case V4L2_CID_BRIGHTNESS:
+               case V4L2_CID_CONTRAST:
+               case V4L2_CID_SATURATION:
+               case V4L2_CID_HUE:
+                       return v4l2_ctrl_query_fill_std(qc);
+               default:
+                       break;
+               }
+
+               switch (qc->id) {
+               case V4L2_CID_AUDIO_VOLUME:
+               case V4L2_CID_AUDIO_MUTE:
+               case V4L2_CID_AUDIO_BALANCE:
+               case V4L2_CID_AUDIO_BASS:
+               case V4L2_CID_AUDIO_TREBLE:
+                       return v4l2_ctrl_query_fill_std(qc);
+               default:
+                       return -EINVAL;
+               }
+               return -EINVAL;
+       }
+
+       case VIDIOC_G_STD:
+               *(v4l2_std_id *)arg = state->std;
+               break;
+
+       case VIDIOC_S_STD:
+               if (state->radio == 0 && state->std == *(v4l2_std_id *)arg)
+                       return 0;
+               state->radio = 0;
+               state->std = *(v4l2_std_id *)arg;
+               return set_v4lstd(cx);
+
+       case AUDC_SET_RADIO:
+               state->radio = 1;
+               break;
+
+       case VIDIOC_INT_G_VIDEO_ROUTING:
+               route->input = state->vid_input;
+               route->output = 0;
+               break;
+
+       case VIDIOC_INT_S_VIDEO_ROUTING:
+               return set_input(cx, route->input, state->aud_input);
+
+       case VIDIOC_INT_G_AUDIO_ROUTING:
+               route->input = state->aud_input;
+               route->output = 0;
+               break;
+
+       case VIDIOC_INT_S_AUDIO_ROUTING:
+               return set_input(cx, state->vid_input, route->input);
+
+       case VIDIOC_S_FREQUENCY:
+               input_change(cx);
+               break;
+
+       case VIDIOC_G_TUNER:
+       {
+               u8 vpres = cx18_av_read(cx, 0x40e) & 0x20;
+               u8 mode;
+               int val = 0;
+
+               if (state->radio)
+                       break;
+
+               vt->signal = vpres ? 0xffff : 0x0;
+
+               vt->capability |=
+                   V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
+                   V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
+
+               mode = cx18_av_read(cx, 0x804);
+
+               /* get rxsubchans and audmode */
+               if ((mode & 0xf) == 1)
+                       val |= V4L2_TUNER_SUB_STEREO;
+               else
+                       val |= V4L2_TUNER_SUB_MONO;
+
+               if (mode == 2 || mode == 4)
+                       val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+
+               if (mode & 0x10)
+                       val |= V4L2_TUNER_SUB_SAP;
+
+               vt->rxsubchans = val;
+               vt->audmode = state->audmode;
+               break;
+       }
+
+       case VIDIOC_S_TUNER:
+               if (state->radio)
+                       break;
+
+               switch (vt->audmode) {
+               case V4L2_TUNER_MODE_MONO:
+                       /* mono      -> mono
+                          stereo    -> mono
+                          bilingual -> lang1 */
+                       cx18_av_and_or(cx, 0x809, ~0xf, 0x00);
+                       break;
+               case V4L2_TUNER_MODE_STEREO:
+               case V4L2_TUNER_MODE_LANG1:
+                       /* mono      -> mono
+                          stereo    -> stereo
+                          bilingual -> lang1 */
+                       cx18_av_and_or(cx, 0x809, ~0xf, 0x04);
+                       break;
+               case V4L2_TUNER_MODE_LANG1_LANG2:
+                       /* mono      -> mono
+                          stereo    -> stereo
+                          bilingual -> lang1/lang2 */
+                       cx18_av_and_or(cx, 0x809, ~0xf, 0x07);
+                       break;
+               case V4L2_TUNER_MODE_LANG2:
+                       /* mono      -> mono
+                          stereo    -> stereo
+                          bilingual -> lang2 */
+                       cx18_av_and_or(cx, 0x809, ~0xf, 0x01);
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               state->audmode = vt->audmode;
+               break;
+
+       case VIDIOC_G_FMT:
+               return get_v4lfmt(cx, (struct v4l2_format *)arg);
+
+       case VIDIOC_S_FMT:
+               return set_v4lfmt(cx, (struct v4l2_format *)arg);
+
+       case VIDIOC_INT_RESET:
+               cx18_av_initialize(cx);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* ----------------------------------------------------------------------- */
+
+static void log_video_status(struct cx18 *cx)
+{
+       static const char *const fmt_strs[] = {
+               "0x0",
+               "NTSC-M", "NTSC-J", "NTSC-4.43",
+               "PAL-BDGHI", "PAL-M", "PAL-N", "PAL-Nc", "PAL-60",
+               "0x9", "0xA", "0xB",
+               "SECAM",
+               "0xD", "0xE", "0xF"
+       };
+
+       struct cx18_av_state *state = &cx->av_state;
+       u8 vidfmt_sel = cx18_av_read(cx, 0x400) & 0xf;
+       u8 gen_stat1 = cx18_av_read(cx, 0x40d);
+       u8 gen_stat2 = cx18_av_read(cx, 0x40e);
+       int vid_input = state->vid_input;
+
+       CX18_INFO("Video signal:              %spresent\n",
+                   (gen_stat2 & 0x20) ? "" : "not ");
+       CX18_INFO("Detected format:           %s\n",
+                   fmt_strs[gen_stat1 & 0xf]);
+
+       CX18_INFO("Specified standard:        %s\n",
+                   vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection");
+
+       if (vid_input >= CX18_AV_COMPOSITE1 &&
+           vid_input <= CX18_AV_COMPOSITE8) {
+               CX18_INFO("Specified video input:     Composite %d\n",
+                       vid_input - CX18_AV_COMPOSITE1 + 1);
+       } else {
+               CX18_INFO("Specified video input:     S-Video (Luma In%d, Chroma In%d)\n",
+                       (vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8);
+       }
+
+       CX18_INFO("Specified audioclock freq: %d Hz\n", state->audclk_freq);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void log_audio_status(struct cx18 *cx)
+{
+       struct cx18_av_state *state = &cx->av_state;
+       u8 download_ctl = cx18_av_read(cx, 0x803);
+       u8 mod_det_stat0 = cx18_av_read(cx, 0x805);
+       u8 mod_det_stat1 = cx18_av_read(cx, 0x804);
+       u8 audio_config = cx18_av_read(cx, 0x808);
+       u8 pref_mode = cx18_av_read(cx, 0x809);
+       u8 afc0 = cx18_av_read(cx, 0x80b);
+       u8 mute_ctl = cx18_av_read(cx, 0x8d3);
+       int aud_input = state->aud_input;
+       char *p;
+
+       switch (mod_det_stat0) {
+       case 0x00: p = "mono"; break;
+       case 0x01: p = "stereo"; break;
+       case 0x02: p = "dual"; break;
+       case 0x04: p = "tri"; break;
+       case 0x10: p = "mono with SAP"; break;
+       case 0x11: p = "stereo with SAP"; break;
+       case 0x12: p = "dual with SAP"; break;
+       case 0x14: p = "tri with SAP"; break;
+       case 0xfe: p = "forced mode"; break;
+       default: p = "not defined";
+       }
+       CX18_INFO("Detected audio mode:       %s\n", p);
+
+       switch (mod_det_stat1) {
+       case 0x00: p = "BTSC"; break;
+       case 0x01: p = "EIAJ"; break;
+       case 0x02: p = "A2-M"; break;
+       case 0x03: p = "A2-BG"; break;
+       case 0x04: p = "A2-DK1"; break;
+       case 0x05: p = "A2-DK2"; break;
+       case 0x06: p = "A2-DK3"; break;
+       case 0x07: p = "A1 (6.0 MHz FM Mono)"; break;
+       case 0x08: p = "AM-L"; break;
+       case 0x09: p = "NICAM-BG"; break;
+       case 0x0a: p = "NICAM-DK"; break;
+       case 0x0b: p = "NICAM-I"; break;
+       case 0x0c: p = "NICAM-L"; break;
+       case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break;
+       case 0xff: p = "no detected audio standard"; break;
+       default: p = "not defined";
+       }
+       CX18_INFO("Detected audio standard:   %s\n", p);
+       CX18_INFO("Audio muted:               %s\n",
+                   (mute_ctl & 0x2) ? "yes" : "no");
+       CX18_INFO("Audio microcontroller:     %s\n",
+                   (download_ctl & 0x10) ? "running" : "stopped");
+
+       switch (audio_config >> 4) {
+       case 0x00: p = "BTSC"; break;
+       case 0x01: p = "EIAJ"; break;
+       case 0x02: p = "A2-M"; break;
+       case 0x03: p = "A2-BG"; break;
+       case 0x04: p = "A2-DK1"; break;
+       case 0x05: p = "A2-DK2"; break;
+       case 0x06: p = "A2-DK3"; break;
+       case 0x07: p = "A1 (6.0 MHz FM Mono)"; break;
+       case 0x08: p = "AM-L"; break;
+       case 0x09: p = "NICAM-BG"; break;
+       case 0x0a: p = "NICAM-DK"; break;
+       case 0x0b: p = "NICAM-I"; break;
+       case 0x0c: p = "NICAM-L"; break;
+       case 0x0d: p = "FM radio"; break;
+       case 0x0f: p = "automatic detection"; break;
+       default: p = "undefined";
+       }
+       CX18_INFO("Configured audio standard: %s\n", p);
+
+       if ((audio_config >> 4) < 0xF) {
+               switch (audio_config & 0xF) {
+               case 0x00: p = "MONO1 (LANGUAGE A/Mono L+R channel for BTSC, EIAJ, A2)"; break;
+               case 0x01: p = "MONO2 (LANGUAGE B)"; break;
+               case 0x02: p = "MONO3 (STEREO forced MONO)"; break;
+               case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break;
+               case 0x04: p = "STEREO"; break;
+               case 0x05: p = "DUAL1 (AB)"; break;
+               case 0x06: p = "DUAL2 (AC) (FM)"; break;
+               case 0x07: p = "DUAL3 (BC) (FM)"; break;
+               case 0x08: p = "DUAL4 (AC) (AM)"; break;
+               case 0x09: p = "DUAL5 (BC) (AM)"; break;
+               case 0x0a: p = "SAP"; break;
+               default: p = "undefined";
+               }
+               CX18_INFO("Configured audio mode:     %s\n", p);
+       } else {
+               switch (audio_config & 0xF) {
+               case 0x00: p = "BG"; break;
+               case 0x01: p = "DK1"; break;
+               case 0x02: p = "DK2"; break;
+               case 0x03: p = "DK3"; break;
+               case 0x04: p = "I"; break;
+               case 0x05: p = "L"; break;
+               case 0x06: p = "BTSC"; break;
+               case 0x07: p = "EIAJ"; break;
+               case 0x08: p = "A2-M"; break;
+               case 0x09: p = "FM Radio"; break;
+               case 0x0f: p = "automatic standard and mode detection"; break;
+               default: p = "undefined";
+               }
+               CX18_INFO("Configured audio system:   %s\n", p);
+       }
+
+       if (aud_input)
+               CX18_INFO("Specified audio input:     Tuner (In%d)\n",
+                               aud_input);
+       else
+               CX18_INFO("Specified audio input:     External\n");
+
+       switch (pref_mode & 0xf) {
+       case 0: p = "mono/language A"; break;
+       case 1: p = "language B"; break;
+       case 2: p = "language C"; break;
+       case 3: p = "analog fallback"; break;
+       case 4: p = "stereo"; break;
+       case 5: p = "language AC"; break;
+       case 6: p = "language BC"; break;
+       case 7: p = "language AB"; break;
+       default: p = "undefined";
+       }
+       CX18_INFO("Preferred audio mode:      %s\n", p);
+
+       if ((audio_config & 0xf) == 0xf) {
+               switch ((afc0 >> 2) & 0x1) {
+               case 0: p = "system DK"; break;
+               case 1: p = "system L"; break;
+               }
+               CX18_INFO("Selected 65 MHz format:    %s\n", p);
+
+               switch (afc0 & 0x3) {
+               case 0: p = "BTSC"; break;
+               case 1: p = "EIAJ"; break;
+               case 2: p = "A2-M"; break;
+               default: p = "undefined";
+               }
+               CX18_INFO("Selected 45 MHz format:    %s\n", p);
+       }
+}
diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h
new file mode 100644 (file)
index 0000000..786901d
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ *  cx18 ADEC header
+ *
+ *  Derived from cx25840-core.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+#ifndef _CX18_AV_CORE_H_
+#define _CX18_AV_CORE_H_
+
+struct cx18;
+
+enum cx18_av_video_input {
+       /* Composite video inputs In1-In8 */
+       CX18_AV_COMPOSITE1 = 1,
+       CX18_AV_COMPOSITE2,
+       CX18_AV_COMPOSITE3,
+       CX18_AV_COMPOSITE4,
+       CX18_AV_COMPOSITE5,
+       CX18_AV_COMPOSITE6,
+       CX18_AV_COMPOSITE7,
+       CX18_AV_COMPOSITE8,
+
+       /* S-Video inputs consist of one luma input (In1-In4) ORed with one
+          chroma input (In5-In8) */
+       CX18_AV_SVIDEO_LUMA1 = 0x10,
+       CX18_AV_SVIDEO_LUMA2 = 0x20,
+       CX18_AV_SVIDEO_LUMA3 = 0x30,
+       CX18_AV_SVIDEO_LUMA4 = 0x40,
+       CX18_AV_SVIDEO_CHROMA4 = 0x400,
+       CX18_AV_SVIDEO_CHROMA5 = 0x500,
+       CX18_AV_SVIDEO_CHROMA6 = 0x600,
+       CX18_AV_SVIDEO_CHROMA7 = 0x700,
+       CX18_AV_SVIDEO_CHROMA8 = 0x800,
+
+       /* S-Video aliases for common luma/chroma combinations */
+       CX18_AV_SVIDEO1 = 0x510,
+       CX18_AV_SVIDEO2 = 0x620,
+       CX18_AV_SVIDEO3 = 0x730,
+       CX18_AV_SVIDEO4 = 0x840,
+};
+
+enum cx18_av_audio_input {
+       /* Audio inputs: serial or In4-In8 */
+       CX18_AV_AUDIO_SERIAL,
+       CX18_AV_AUDIO4 = 4,
+       CX18_AV_AUDIO5,
+       CX18_AV_AUDIO6,
+       CX18_AV_AUDIO7,
+       CX18_AV_AUDIO8,
+};
+
+struct cx18_av_state {
+       int radio;
+       v4l2_std_id std;
+       enum cx18_av_video_input vid_input;
+       enum cx18_av_audio_input aud_input;
+       u32 audclk_freq;
+       int audmode;
+       int vbi_line_offset;
+       u32 id;
+       u32 rev;
+       int is_initialized;
+};
+
+
+/* Registers */
+#define CXADEC_CHIP_TYPE_TIGER     0x837
+#define CXADEC_CHIP_TYPE_MAKO      0x843
+
+#define CXADEC_HOST_REG1           0x000
+#define CXADEC_HOST_REG2           0x001
+
+#define CXADEC_CHIP_CTRL           0x100
+#define CXADEC_AFE_CTRL            0x104
+#define CXADEC_PLL_CTRL1           0x108
+#define CXADEC_VID_PLL_FRAC        0x10C
+#define CXADEC_AUX_PLL_FRAC        0x110
+#define CXADEC_PIN_CTRL1           0x114
+#define CXADEC_PIN_CTRL2           0x118
+#define CXADEC_PIN_CFG1            0x11C
+#define CXADEC_PIN_CFG2            0x120
+
+#define CXADEC_PIN_CFG3            0x124
+#define CXADEC_I2S_MCLK            0x127
+
+#define CXADEC_AUD_LOCK1           0x128
+#define CXADEC_AUD_LOCK2           0x12C
+#define CXADEC_POWER_CTRL          0x130
+#define CXADEC_AFE_DIAG_CTRL1      0x134
+#define CXADEC_AFE_DIAG_CTRL2      0x138
+#define CXADEC_AFE_DIAG_CTRL3      0x13C
+#define CXADEC_PLL_DIAG_CTRL       0x140
+#define CXADEC_TEST_CTRL1          0x144
+#define CXADEC_TEST_CTRL2          0x148
+#define CXADEC_BIST_STAT           0x14C
+#define CXADEC_DLL1_DIAG_CTRL      0x158
+#define CXADEC_DLL2_DIAG_CTRL      0x15C
+
+/* IR registers */
+#define CXADEC_IR_CTRL_REG         0x200
+#define CXADEC_IR_TXCLK_REG        0x204
+#define CXADEC_IR_RXCLK_REG        0x208
+#define CXADEC_IR_CDUTY_REG        0x20C
+#define CXADEC_IR_STAT_REG         0x210
+#define CXADEC_IR_IRQEN_REG        0x214
+#define CXADEC_IR_FILTER_REG       0x218
+#define CXADEC_IR_FIFO_REG         0x21C
+
+/* Video Registers */
+#define CXADEC_MODE_CTRL           0x400
+#define CXADEC_OUT_CTRL1           0x404
+#define CXADEC_OUT_CTRL2           0x408
+#define CXADEC_GEN_STAT            0x40C
+#define CXADEC_INT_STAT_MASK       0x410
+#define CXADEC_LUMA_CTRL           0x414
+
+#define CXADEC_BRIGHTNESS_CTRL_BYTE 0x414
+#define CXADEC_CONTRAST_CTRL_BYTE  0x415
+#define CXADEC_LUMA_CTRL_BYTE_3    0x416
+
+#define CXADEC_HSCALE_CTRL         0x418
+#define CXADEC_VSCALE_CTRL         0x41C
+
+#define CXADEC_CHROMA_CTRL         0x420
+
+#define CXADEC_USAT_CTRL_BYTE      0x420
+#define CXADEC_VSAT_CTRL_BYTE      0x421
+#define CXADEC_HUE_CTRL_BYTE       0x422
+
+#define CXADEC_VBI_LINE_CTRL1      0x424
+#define CXADEC_VBI_LINE_CTRL2      0x428
+#define CXADEC_VBI_LINE_CTRL3      0x42C
+#define CXADEC_VBI_LINE_CTRL4      0x430
+#define CXADEC_VBI_LINE_CTRL5      0x434
+#define CXADEC_VBI_FC_CFG          0x438
+#define CXADEC_VBI_MISC_CFG1       0x43C
+#define CXADEC_VBI_MISC_CFG2       0x440
+#define CXADEC_VBI_PAY1            0x444
+#define CXADEC_VBI_PAY2            0x448
+#define CXADEC_VBI_CUST1_CFG1      0x44C
+#define CXADEC_VBI_CUST1_CFG2      0x450
+#define CXADEC_VBI_CUST1_CFG3      0x454
+#define CXADEC_VBI_CUST2_CFG1      0x458
+#define CXADEC_VBI_CUST2_CFG2      0x45C
+#define CXADEC_VBI_CUST2_CFG3      0x460
+#define CXADEC_VBI_CUST3_CFG1      0x464
+#define CXADEC_VBI_CUST3_CFG2      0x468
+#define CXADEC_VBI_CUST3_CFG3      0x46C
+#define CXADEC_HORIZ_TIM_CTRL      0x470
+#define CXADEC_VERT_TIM_CTRL       0x474
+#define CXADEC_SRC_COMB_CFG        0x478
+#define CXADEC_CHROMA_VBIOFF_CFG   0x47C
+#define CXADEC_FIELD_COUNT         0x480
+#define CXADEC_MISC_TIM_CTRL       0x484
+#define CXADEC_DFE_CTRL1           0x488
+#define CXADEC_DFE_CTRL2           0x48C
+#define CXADEC_DFE_CTRL3           0x490
+#define CXADEC_PLL_CTRL2           0x494
+#define CXADEC_HTL_CTRL            0x498
+#define CXADEC_COMB_CTRL           0x49C
+#define CXADEC_CRUSH_CTRL          0x4A0
+#define CXADEC_SOFT_RST_CTRL       0x4A4
+#define CXADEC_MV_DT_CTRL2         0x4A8
+#define CXADEC_MV_DT_CTRL3         0x4AC
+#define CXADEC_MISC_DIAG_CTRL      0x4B8
+
+#define CXADEC_DL_CTL              0x800
+#define CXADEC_DL_CTL_ADDRESS_LOW  0x800   /* Byte 1 in DL_CTL */
+#define CXADEC_DL_CTL_ADDRESS_HIGH 0x801   /* Byte 2 in DL_CTL */
+#define CXADEC_DL_CTL_DATA         0x802   /* Byte 3 in DL_CTL */
+#define CXADEC_DL_CTL_CONTROL      0x803   /* Byte 4 in DL_CTL */
+
+#define CXADEC_STD_DET_STATUS      0x804
+
+#define CXADEC_STD_DET_CTL         0x808
+#define CXADEC_STD_DET_CTL_AUD_CTL   0x808 /* Byte 1 in STD_DET_CTL */
+#define CXADEC_STD_DET_CTL_PREF_MODE 0x809 /* Byte 2 in STD_DET_CTL */
+
+#define CXADEC_DW8051_INT          0x80C
+#define CXADEC_GENERAL_CTL         0x810
+#define CXADEC_AAGC_CTL            0x814
+#define CXADEC_IF_SRC_CTL          0x818
+#define CXADEC_ANLOG_DEMOD_CTL     0x81C
+#define CXADEC_ROT_FREQ_CTL        0x820
+#define CXADEC_FM1_CTL             0x824
+#define CXADEC_PDF_CTL             0x828
+#define CXADEC_DFT1_CTL1           0x82C
+#define CXADEC_DFT1_CTL2           0x830
+#define CXADEC_DFT_STATUS          0x834
+#define CXADEC_DFT2_CTL1           0x838
+#define CXADEC_DFT2_CTL2           0x83C
+#define CXADEC_DFT2_STATUS         0x840
+#define CXADEC_DFT3_CTL1           0x844
+#define CXADEC_DFT3_CTL2           0x848
+#define CXADEC_DFT3_STATUS         0x84C
+#define CXADEC_DFT4_CTL1           0x850
+#define CXADEC_DFT4_CTL2           0x854
+#define CXADEC_DFT4_STATUS         0x858
+#define CXADEC_AM_MTS_DET          0x85C
+#define CXADEC_ANALOG_MUX_CTL      0x860
+#define CXADEC_DIG_PLL_CTL1        0x864
+#define CXADEC_DIG_PLL_CTL2        0x868
+#define CXADEC_DIG_PLL_CTL3        0x86C
+#define CXADEC_DIG_PLL_CTL4        0x870
+#define CXADEC_DIG_PLL_CTL5        0x874
+#define CXADEC_DEEMPH_GAIN_CTL     0x878
+#define CXADEC_DEEMPH_COEF1        0x87C
+#define CXADEC_DEEMPH_COEF2        0x880
+#define CXADEC_DBX1_CTL1           0x884
+#define CXADEC_DBX1_CTL2           0x888
+#define CXADEC_DBX1_STATUS         0x88C
+#define CXADEC_DBX2_CTL1           0x890
+#define CXADEC_DBX2_CTL2           0x894
+#define CXADEC_DBX2_STATUS         0x898
+#define CXADEC_AM_FM_DIFF          0x89C
+
+/* NICAM registers go here */
+#define CXADEC_NICAM_STATUS        0x8C8
+#define CXADEC_DEMATRIX_CTL        0x8CC
+
+#define CXADEC_PATH1_CTL1          0x8D0
+#define CXADEC_PATH1_VOL_CTL       0x8D4
+#define CXADEC_PATH1_EQ_CTL        0x8D8
+#define CXADEC_PATH1_SC_CTL        0x8DC
+
+#define CXADEC_PATH2_CTL1          0x8E0
+#define CXADEC_PATH2_VOL_CTL       0x8E4
+#define CXADEC_PATH2_EQ_CTL        0x8E8
+#define CXADEC_PATH2_SC_CTL        0x8EC
+
+#define CXADEC_SRC_CTL             0x8F0
+#define CXADEC_SRC_LF_COEF         0x8F4
+#define CXADEC_SRC1_CTL            0x8F8
+#define CXADEC_SRC2_CTL            0x8FC
+#define CXADEC_SRC3_CTL            0x900
+#define CXADEC_SRC4_CTL            0x904
+#define CXADEC_SRC5_CTL            0x908
+#define CXADEC_SRC6_CTL            0x90C
+
+#define CXADEC_BASEBAND_OUT_SEL    0x910
+#define CXADEC_I2S_IN_CTL          0x914
+#define CXADEC_I2S_OUT_CTL         0x918
+#define CXADEC_AC97_CTL            0x91C
+#define CXADEC_QAM_PDF             0x920
+#define CXADEC_QAM_CONST_DEC       0x924
+#define CXADEC_QAM_ROTATOR_FREQ    0x948
+
+/* Bit defintions / settings used in Mako Audio */
+#define CXADEC_PREF_MODE_MONO_LANGA        0
+#define CXADEC_PREF_MODE_MONO_LANGB        1
+#define CXADEC_PREF_MODE_MONO_LANGC        2
+#define CXADEC_PREF_MODE_FALLBACK          3
+#define CXADEC_PREF_MODE_STEREO            4
+#define CXADEC_PREF_MODE_DUAL_LANG_AC      5
+#define CXADEC_PREF_MODE_DUAL_LANG_BC      6
+#define CXADEC_PREF_MODE_DUAL_LANG_AB      7
+
+
+#define CXADEC_DETECT_STEREO               1
+#define CXADEC_DETECT_DUAL                 2
+#define CXADEC_DETECT_TRI                  4
+#define CXADEC_DETECT_SAP                  0x10
+#define CXADEC_DETECT_NO_SIGNAL            0xFF
+
+#define CXADEC_SELECT_AUDIO_STANDARD_BG    0xF0  /* NICAM BG and A2 BG */
+#define CXADEC_SELECT_AUDIO_STANDARD_DK1   0xF1  /* NICAM DK and A2 DK */
+#define CXADEC_SELECT_AUDIO_STANDARD_DK2   0xF2
+#define CXADEC_SELECT_AUDIO_STANDARD_DK3   0xF3
+#define CXADEC_SELECT_AUDIO_STANDARD_I     0xF4  /* NICAM I and A1 */
+#define CXADEC_SELECT_AUDIO_STANDARD_L     0xF5  /* NICAM L and System L AM */
+#define CXADEC_SELECT_AUDIO_STANDARD_BTSC  0xF6
+#define CXADEC_SELECT_AUDIO_STANDARD_EIAJ  0xF7
+#define CXADEC_SELECT_AUDIO_STANDARD_A2_M  0xF8  /* A2 M */
+#define CXADEC_SELECT_AUDIO_STANDARD_FM    0xF9  /* FM radio */
+#define CXADEC_SELECT_AUDIO_STANDARD_AUTO  0xFF  /* Auto detect */
+
+/* ----------------------------------------------------------------------- */
+/* cx18_av-core.c                                                         */
+int cx18_av_write(struct cx18 *cx, u16 addr, u8 value);
+int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value);
+u8 cx18_av_read(struct cx18 *cx, u16 addr);
+u32 cx18_av_read4(struct cx18 *cx, u16 addr);
+int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value);
+int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value);
+int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg);
+
+/* ----------------------------------------------------------------------- */
+/* cx18_av-firmware.c                                                      */
+int cx18_av_loadfw(struct cx18 *cx);
+
+/* ----------------------------------------------------------------------- */
+/* cx18_av-audio.c                                                         */
+int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg);
+void cx18_av_audio_set_path(struct cx18 *cx);
+
+/* ----------------------------------------------------------------------- */
+/* cx18_av-vbi.c                                                           */
+void cx18_av_vbi_setup(struct cx18 *cx);
+int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg);
+
+#endif
diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c
new file mode 100644 (file)
index 0000000..526e142
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ *  cx18 ADEC firmware functions
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+#include "cx18-driver.h"
+#include <linux/firmware.h>
+
+#define FWFILE "v4l-cx23418-dig.fw"
+
+int cx18_av_loadfw(struct cx18 *cx)
+{
+       const struct firmware *fw = NULL;
+       u32 size;
+       u32 v;
+       u8 *ptr;
+       int i;
+
+       if (request_firmware(&fw, FWFILE, &cx->dev->dev) != 0) {
+               CX18_ERR("unable to open firmware %s\n", FWFILE);
+               return -EINVAL;
+       }
+
+       cx18_av_write4(cx, CXADEC_CHIP_CTRL, 0x00010000);
+       cx18_av_write(cx, CXADEC_STD_DET_CTL, 0xf6); /* Byte 0 */
+
+       /* Reset the Mako core (Register is undocumented.) */
+       cx18_av_write4(cx, 0x8100, 0x00010000);
+
+       /* Put the 8051 in reset and enable firmware upload */
+       cx18_av_write4(cx, CXADEC_DL_CTL, 0x0F000000);
+
+       ptr = fw->data;
+       size = fw->size;
+
+       for (i = 0; i < size; i++) {
+               u32 dl_control = 0x0F000000 | ((u32)ptr[i] << 16);
+               u32 value = 0;
+               int retries;
+
+               for (retries = 0; retries < 5; retries++) {
+                       cx18_av_write4(cx, CXADEC_DL_CTL, dl_control);
+                       value = cx18_av_read4(cx, CXADEC_DL_CTL);
+                       if ((value & 0x3F00) == (dl_control & 0x3F00))
+                               break;
+               }
+               if (retries >= 5) {
+                       CX18_ERR("unable to load firmware %s\n", FWFILE);
+                       release_firmware(fw);
+                       return -EIO;
+               }
+       }
+
+       cx18_av_write4(cx, CXADEC_DL_CTL, 0x13000000 | fw->size);
+
+       /* Output to the 416 */
+       cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x78000);
+
+       /* Audio input control 1 set to Sony mode */
+       /* Audio output input 2 is 0 for slave operation input */
+       /* 0xC4000914[5]: 0 = left sample on WS=0, 1 = left sample on WS=1 */
+       /* 0xC4000914[7]: 0 = Philips mode, 1 = Sony mode (1st SCK rising edge
+          after WS transition for first bit of audio word. */
+       cx18_av_write4(cx, CXADEC_I2S_IN_CTL, 0x000000A0);
+
+       /* Audio output control 1 is set to Sony mode */
+       /* Audio output control 2 is set to 1 for master mode */
+       /* 0xC4000918[5]: 0 = left sample on WS=0, 1 = left sample on WS=1 */
+       /* 0xC4000918[7]: 0 = Philips mode, 1 = Sony mode (1st SCK rising edge
+          after WS transition for first bit of audio word. */
+       /* 0xC4000918[8]: 0 = slave operation, 1 = master (SCK_OUT and WS_OUT
+          are generated) */
+       cx18_av_write4(cx, CXADEC_I2S_OUT_CTL, 0x000001A0);
+
+       /* set alt I2s master clock to /16 and enable alt divider i2s
+          passthrough */
+       cx18_av_write4(cx, CXADEC_PIN_CFG3, 0x5000B687);
+
+       cx18_av_write4(cx, CXADEC_STD_DET_CTL, 0x000000F6);
+       /* CxDevWrReg(CXADEC_STD_DET_CTL, 0x000000FF); */
+
+       /* Set bit 0 in register 0x9CC to signify that this is MiniMe. */
+       /* Register 0x09CC is defined by the Merlin firmware, and doesn't
+          have a name in the spec. */
+       cx18_av_write4(cx, 0x09CC, 1);
+
+#define CX18_AUDIO_ENABLE              0xc72014
+       v = read_reg(CX18_AUDIO_ENABLE);
+       /* If bit 11 is 1 */
+       if (v & 0x800)
+               write_reg(v & 0xFFFFFBFF, CX18_AUDIO_ENABLE); /* Clear bit 10 */
+
+       /* Enable WW auto audio standard detection */
+       v = cx18_av_read4(cx, CXADEC_STD_DET_CTL);
+       v |= 0xFF;   /* Auto by default */
+       v |= 0x400;  /* Stereo by default */
+       v |= 0x14000000;
+       cx18_av_write4(cx, CXADEC_STD_DET_CTL, v);
+
+       release_firmware(fw);
+
+       CX18_INFO("loaded %s firmware (%d bytes)\n", FWFILE, size);
+       return 0;
+}
diff --git a/drivers/media/video/cx18/cx18-av-vbi.c b/drivers/media/video/cx18/cx18-av-vbi.c
new file mode 100644 (file)
index 0000000..d09f1da
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ *  cx18 ADEC VBI functions
+ *
+ *  Derived from cx25840-vbi.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+
+#include "cx18-driver.h"
+
+static int odd_parity(u8 c)
+{
+       c ^= (c >> 4);
+       c ^= (c >> 2);
+       c ^= (c >> 1);
+
+       return c & 1;
+}
+
+static int decode_vps(u8 *dst, u8 *p)
+{
+       static const u8 biphase_tbl[] = {
+               0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+               0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+               0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
+               0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
+               0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
+               0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
+               0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+               0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+               0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
+               0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
+               0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
+               0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
+               0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
+               0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
+               0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
+               0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
+               0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
+               0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
+               0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
+               0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
+               0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
+               0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
+               0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
+               0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
+               0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+               0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+               0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
+               0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
+               0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
+               0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
+               0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+               0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+       };
+
+       u8 c, err = 0;
+       int i;
+
+       for (i = 0; i < 2 * 13; i += 2) {
+               err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
+               c = (biphase_tbl[p[i + 1]] & 0xf) |
+                   ((biphase_tbl[p[i]] & 0xf) << 4);
+               dst[i / 2] = c;
+       }
+
+       return err & 0xf0;
+}
+
+void cx18_av_vbi_setup(struct cx18 *cx)
+{
+       struct cx18_av_state *state = &cx->av_state;
+       v4l2_std_id std = state->std;
+       int hblank, hactive, burst, vblank, vactive, sc;
+       int vblank656, src_decimation;
+       int luma_lpf, uv_lpf, comb;
+       u32 pll_int, pll_frac, pll_post;
+
+       /* datasheet startup, step 8d */
+       if (std & ~V4L2_STD_NTSC)
+               cx18_av_write(cx, 0x49f, 0x11);
+       else
+               cx18_av_write(cx, 0x49f, 0x14);
+
+       if (std & V4L2_STD_625_50) {
+               hblank = 0x084;
+               hactive = 0x2d0;
+               burst = 0x5d;
+               vblank = 0x024;
+               vactive = 0x244;
+               vblank656 = 0x28;
+               src_decimation = 0x21f;
+
+               luma_lpf = 2;
+               if (std & V4L2_STD_SECAM) {
+                       uv_lpf = 0;
+                       comb = 0;
+                       sc = 0x0a425f;
+               } else if (std == V4L2_STD_PAL_Nc) {
+                       uv_lpf = 1;
+                       comb = 0x20;
+                       sc = 556453;
+               } else {
+                       uv_lpf = 1;
+                       comb = 0x20;
+                       sc = 0x0a8263;
+               }
+       } else {
+               hactive = 720;
+               hblank = 122;
+               vactive = 487;
+               luma_lpf = 1;
+               uv_lpf = 1;
+
+               src_decimation = 0x21f;
+               if (std == V4L2_STD_PAL_60) {
+                       vblank = 26;
+                       vblank656 = 26;
+                       burst = 0x5b;
+                       luma_lpf = 2;
+                       comb = 0x20;
+                       sc = 0x0a8263;
+               } else if (std == V4L2_STD_PAL_M) {
+                       vblank = 20;
+                       vblank656 = 24;
+                       burst = 0x61;
+                       comb = 0x20;
+
+                       sc = 555452;
+               } else {
+                       vblank = 26;
+                       vblank656 = 26;
+                       burst = 0x5b;
+                       comb = 0x66;
+                       sc = 556063;
+               }
+       }
+
+       /* DEBUG: Displays configured PLL frequency */
+       pll_int = cx18_av_read(cx, 0x108);
+       pll_frac = cx18_av_read4(cx, 0x10c) & 0x1ffffff;
+       pll_post = cx18_av_read(cx, 0x109);
+       CX18_DEBUG_INFO("PLL regs = int: %u, frac: %u, post: %u\n",
+                       pll_int, pll_frac, pll_post);
+
+       if (pll_post) {
+               int fin, fsc;
+               int pll = 28636363L * ((((u64)pll_int) << 25) + pll_frac);
+
+               pll >>= 25;
+               pll /= pll_post;
+               CX18_DEBUG_INFO("PLL = %d.%06d MHz\n",
+                                       pll / 1000000, pll % 1000000);
+               CX18_DEBUG_INFO("PLL/8 = %d.%06d MHz\n",
+                                       pll / 8000000, (pll / 8) % 1000000);
+
+               fin = ((u64)src_decimation * pll) >> 12;
+               CX18_DEBUG_INFO("ADC Sampling freq = %d.%06d MHz\n",
+                                       fin / 1000000, fin % 1000000);
+
+               fsc = (((u64)sc) * pll) >> 24L;
+               CX18_DEBUG_INFO("Chroma sub-carrier freq = %d.%06d MHz\n",
+                                       fsc / 1000000, fsc % 1000000);
+
+               CX18_DEBUG_INFO("hblank %i, hactive %i, "
+                       "vblank %i , vactive %i, vblank656 %i, src_dec %i,"
+                       "burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x,"
+                       " sc 0x%06x\n",
+                       hblank, hactive, vblank, vactive, vblank656,
+                       src_decimation, burst, luma_lpf, uv_lpf, comb, sc);
+       }
+
+       /* Sets horizontal blanking delay and active lines */
+       cx18_av_write(cx, 0x470, hblank);
+       cx18_av_write(cx, 0x471, 0xff & (((hblank >> 8) & 0x3) |
+                                               (hactive << 4)));
+       cx18_av_write(cx, 0x472, hactive >> 4);
+
+       /* Sets burst gate delay */
+       cx18_av_write(cx, 0x473, burst);
+
+       /* Sets vertical blanking delay and active duration */
+       cx18_av_write(cx, 0x474, vblank);
+       cx18_av_write(cx, 0x475, 0xff & (((vblank >> 8) & 0x3) |
+                                               (vactive << 4)));
+       cx18_av_write(cx, 0x476, vactive >> 4);
+       cx18_av_write(cx, 0x477, vblank656);
+
+       /* Sets src decimation rate */
+       cx18_av_write(cx, 0x478, 0xff & src_decimation);
+       cx18_av_write(cx, 0x479, 0xff & (src_decimation >> 8));
+
+       /* Sets Luma and UV Low pass filters */
+       cx18_av_write(cx, 0x47a, luma_lpf << 6 | ((uv_lpf << 4) & 0x30));
+
+       /* Enables comb filters */
+       cx18_av_write(cx, 0x47b, comb);
+
+       /* Sets SC Step*/
+       cx18_av_write(cx, 0x47c, sc);
+       cx18_av_write(cx, 0x47d, 0xff & sc >> 8);
+       cx18_av_write(cx, 0x47e, 0xff & sc >> 16);
+
+       /* Sets VBI parameters */
+       if (std & V4L2_STD_625_50) {
+               cx18_av_write(cx, 0x47f, 0x01);
+               state->vbi_line_offset = 5;
+       } else {
+               cx18_av_write(cx, 0x47f, 0x00);
+               state->vbi_line_offset = 8;
+       }
+}
+
+int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg)
+{
+       struct cx18_av_state *state = &cx->av_state;
+       struct v4l2_format *fmt;
+       struct v4l2_sliced_vbi_format *svbi;
+
+       switch (cmd) {
+       case VIDIOC_G_FMT:
+       {
+               static u16 lcr2vbi[] = {
+                       0, V4L2_SLICED_TELETEXT_B, 0,   /* 1 */
+                       0, V4L2_SLICED_WSS_625, 0,      /* 4 */
+                       V4L2_SLICED_CAPTION_525,        /* 6 */
+                       0, 0, V4L2_SLICED_VPS, 0, 0,    /* 9 */
+                       0, 0, 0, 0
+               };
+               int is_pal = !(state->std & V4L2_STD_525_60);
+               int i;
+
+               fmt = arg;
+               if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
+                       return -EINVAL;
+               svbi = &fmt->fmt.sliced;
+               memset(svbi, 0, sizeof(*svbi));
+               /* we're done if raw VBI is active */
+               if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
+                       break;
+
+               if (is_pal) {
+                       for (i = 7; i <= 23; i++) {
+                               u8 v = cx18_av_read(cx, 0x424 + i - 7);
+
+                               svbi->service_lines[0][i] = lcr2vbi[v >> 4];
+                               svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
+                               svbi->service_set |= svbi->service_lines[0][i] |
+                                       svbi->service_lines[1][i];
+                       }
+               } else {
+                       for (i = 10; i <= 21; i++) {
+                               u8 v = cx18_av_read(cx, 0x424 + i - 10);
+
+                               svbi->service_lines[0][i] = lcr2vbi[v >> 4];
+                               svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
+                               svbi->service_set |= svbi->service_lines[0][i] |
+                                       svbi->service_lines[1][i];
+                       }
+               }
+               break;
+       }
+
+       case VIDIOC_S_FMT:
+       {
+               int is_pal = !(state->std & V4L2_STD_525_60);
+               int vbi_offset = is_pal ? 1 : 0;
+               int i, x;
+               u8 lcr[24];
+
+               fmt = arg;
+               if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
+                       return -EINVAL;
+               svbi = &fmt->fmt.sliced;
+               if (svbi->service_set == 0) {
+                       /* raw VBI */
+                       memset(svbi, 0, sizeof(*svbi));
+
+                       /* Setup VBI */
+                       cx18_av_vbi_setup(cx);
+
+                       /* VBI Offset */
+                       cx18_av_write(cx, 0x47f, vbi_offset);
+                       cx18_av_write(cx, 0x404, 0x2e);
+                       break;
+               }
+
+               for (x = 0; x <= 23; x++)
+                       lcr[x] = 0x00;
+
+               /* Setup VBI */
+               cx18_av_vbi_setup(cx);
+
+               /* Sliced VBI */
+               cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */
+               cx18_av_write(cx, 0x406, 0x13);
+               cx18_av_write(cx, 0x47f, vbi_offset);
+
+               if (is_pal) {
+                       for (i = 0; i <= 6; i++)
+                               svbi->service_lines[0][i] =
+                                       svbi->service_lines[1][i] = 0;
+               } else {
+                       for (i = 0; i <= 9; i++)
+                               svbi->service_lines[0][i] =
+                                       svbi->service_lines[1][i] = 0;
+
+                       for (i = 22; i <= 23; i++)
+                               svbi->service_lines[0][i] =
+                                       svbi->service_lines[1][i] = 0;
+               }
+
+               for (i = 7; i <= 23; i++) {
+                       for (x = 0; x <= 1; x++) {
+                               switch (svbi->service_lines[1-x][i]) {
+                               case V4L2_SLICED_TELETEXT_B:
+                                       lcr[i] |= 1 << (4 * x);
+                                       break;
+                               case V4L2_SLICED_WSS_625:
+                                       lcr[i] |= 4 << (4 * x);
+                                       break;
+                               case V4L2_SLICED_CAPTION_525:
+                                       lcr[i] |= 6 << (4 * x);
+                                       break;
+                               case V4L2_SLICED_VPS:
+                                       lcr[i] |= 9 << (4 * x);
+                                       break;
+                               }
+                       }
+               }
+
+               if (is_pal) {
+                       for (x = 1, i = 0x424; i <= 0x434; i++, x++)
+                               cx18_av_write(cx, i, lcr[6 + x]);
+               } else {
+                       for (x = 1, i = 0x424; i <= 0x430; i++, x++)
+                               cx18_av_write(cx, i, lcr[9 + x]);
+                       for (i = 0x431; i <= 0x434; i++)
+                               cx18_av_write(cx, i, 0);
+               }
+
+               cx18_av_write(cx, 0x43c, 0x16);
+               cx18_av_write(cx, 0x474, is_pal ? 0x2a : 0x22);
+               break;
+       }
+
+       case VIDIOC_INT_DECODE_VBI_LINE:
+       {
+               struct v4l2_decode_vbi_line *vbi = arg;
+               u8 *p = vbi->p;
+               int id1, id2, l, err = 0;
+
+               if (p[0] || p[1] != 0xff || p[2] != 0xff ||
+                   (p[3] != 0x55 && p[3] != 0x91)) {
+                       vbi->line = vbi->type = 0;
+                       break;
+               }
+
+               p += 4;
+               id1 = p[-1];
+               id2 = p[0] & 0xf;
+               l = p[2] & 0x3f;
+               l += state->vbi_line_offset;
+               p += 4;
+
+               switch (id2) {
+               case 1:
+                       id2 = V4L2_SLICED_TELETEXT_B;
+                       break;
+               case 4:
+                       id2 = V4L2_SLICED_WSS_625;
+                       break;
+               case 6:
+                       id2 = V4L2_SLICED_CAPTION_525;
+                       err = !odd_parity(p[0]) || !odd_parity(p[1]);
+                       break;
+               case 9:
+                       id2 = V4L2_SLICED_VPS;
+                       if (decode_vps(p, p) != 0)
+                               err = 1;
+                       break;
+               default:
+                       id2 = 0;
+                       err = 1;
+                       break;
+               }
+
+               vbi->type = err ? 0 : id2;
+               vbi->line = err ? 0 : l;
+               vbi->is_second_field = err ? 0 : (id1 == 0x55);
+               vbi->p = p;
+               break;
+       }
+       }
+
+       return 0;
+}
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c
new file mode 100644 (file)
index 0000000..f5e3ba1
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ *  cx18 functions to query card hardware
+ *
+ *  Derived from ivtv-cards.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 "cx18-driver.h"
+#include "cx18-cards.h"
+#include "cx18-i2c.h"
+#include <media/cs5345.h>
+
+/********************** card configuration *******************************/
+
+/* usual i2c tuner addresses to probe */
+static struct cx18_card_tuner_i2c cx18_i2c_std = {
+       .radio = { I2C_CLIENT_END },
+       .demod = { 0x43, I2C_CLIENT_END },
+       .tv    = { 0x61, 0x60, I2C_CLIENT_END },
+};
+
+/* Please add new PCI IDs to: http://pci-ids.ucw.cz/iii
+   This keeps the PCI ID database up to date. Note that the entries
+   must be added under vendor 0x4444 (Conexant) as subsystem IDs.
+   New vendor IDs should still be added to the vendor ID list. */
+
+/* Hauppauge HVR-1600 cards */
+
+/* Note: for Hauppauge cards the tveeprom information is used instead
+   of PCI IDs */
+static const struct cx18_card cx18_card_hvr1600_esmt = {
+       .type = CX18_CARD_HVR_1600_ESMT,
+       .name = "Hauppauge HVR-1600",
+       .comment = "DVB & VBI are not yet supported\n",
+       .v4l2_capabilities = CX18_CAP_ENCODER,
+       .hw_audio_ctrl = CX18_HW_CX23418,
+       .hw_muxer = CX18_HW_CS5345,
+       .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | CX18_HW_CS5345,
+       .video_inputs = {
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX23418_COMPOSITE7 },
+               { CX18_CARD_INPUT_SVIDEO1,    1, CX23418_SVIDEO1    },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE3 },
+               { CX18_CARD_INPUT_SVIDEO2,    2, CX23418_SVIDEO2    },
+               { CX18_CARD_INPUT_COMPOSITE2, 2, CX23418_COMPOSITE4 },
+       },
+       .audio_inputs = {
+               { CX18_CARD_INPUT_AUD_TUNER,
+                 CX23418_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
+               { CX18_CARD_INPUT_LINE_IN1,
+                 CX23418_AUDIO_SERIAL, CS5345_IN_2 },
+               { CX18_CARD_INPUT_LINE_IN2,
+                 CX23418_AUDIO_SERIAL, CS5345_IN_2 },
+       },
+       .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
+                        CX23418_AUDIO_SERIAL, 0 },
+       .ddr = {
+               /* ESMT M13S128324A-5B memory */
+               .chip_config = 0x003,
+               .refresh = 0x30c,
+               .timing1 = 0x44220e82,
+               .timing2 = 0x08,
+               .tune_lane = 0,
+               .initial_emrs = 0,
+       },
+       .gpio_init.initial_value = 0x3001,
+       .gpio_init.direction = 0x3001,
+       .i2c = &cx18_i2c_std,
+};
+
+static const struct cx18_card cx18_card_hvr1600_samsung = {
+       .type = CX18_CARD_HVR_1600_SAMSUNG,
+       .name = "Hauppauge HVR-1600 (Preproduction)",
+       .comment = "DVB & VBI are not yet supported\n",
+       .v4l2_capabilities = CX18_CAP_ENCODER,
+       .hw_audio_ctrl = CX18_HW_CX23418,
+       .hw_muxer = CX18_HW_CS5345,
+       .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | CX18_HW_CS5345,
+       .video_inputs = {
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX23418_COMPOSITE7 },
+               { CX18_CARD_INPUT_SVIDEO1,    1, CX23418_SVIDEO1    },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE3 },
+               { CX18_CARD_INPUT_SVIDEO2,    2, CX23418_SVIDEO2    },
+               { CX18_CARD_INPUT_COMPOSITE2, 2, CX23418_COMPOSITE4 },
+       },
+       .audio_inputs = {
+               { CX18_CARD_INPUT_AUD_TUNER,
+                 CX23418_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
+               { CX18_CARD_INPUT_LINE_IN1,
+                 CX23418_AUDIO_SERIAL, CS5345_IN_2 },
+               { CX18_CARD_INPUT_LINE_IN2,
+                 CX23418_AUDIO_SERIAL, CS5345_IN_2 },
+       },
+       .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
+                        CX23418_AUDIO_SERIAL, 0 },
+       .ddr = {
+               /* Samsung K4D263238G-VC33 memory */
+               .chip_config = 0x003,
+               .refresh = 0x30c,
+               .timing1 = 0x23230b73,
+               .timing2 = 0x08,
+               .tune_lane = 0,
+               .initial_emrs = 2,
+       },
+       .gpio_init.initial_value = 0x3001,
+       .gpio_init.direction = 0x3001,
+       .i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Compro VideoMate H900: not working at the moment! */
+
+static const struct cx18_card_pci_info cx18_pci_h900[] = {
+       { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_COMPRO, 0xe100 },
+       { 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_h900 = {
+       .type = CX18_CARD_COMPRO_H900,
+       .name = "Compro VideoMate H900",
+       .comment = "Not yet supported!\n",
+       .v4l2_capabilities = 0,
+       .hw_audio_ctrl = CX18_HW_CX23418,
+       .hw_all = CX18_HW_TUNER,
+       .video_inputs = {
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX23418_COMPOSITE7 },
+               { CX18_CARD_INPUT_SVIDEO1,    1, CX23418_SVIDEO1    },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE3 },
+       },
+       .audio_inputs = {
+               { CX18_CARD_INPUT_AUD_TUNER,
+                 CX23418_AUDIO8, 0 },
+               { CX18_CARD_INPUT_LINE_IN1,
+                 CX23418_AUDIO_SERIAL, 0 },
+       },
+       .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
+                        CX23418_AUDIO_SERIAL, 0 },
+       .tuners = {
+               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+       },
+       .ddr = {
+               /* EtronTech EM6A9160TS-5G memory */
+               .chip_config = 0x50003,
+               .refresh = 0x753,
+               .timing1 = 0x24330e84,
+               .timing2 = 0x1f,
+               .tune_lane = 0,
+               .initial_emrs = 0,
+       },
+       .pci_list = cx18_pci_h900,
+       .i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Yuan MPC718: not working at the moment! */
+
+static const struct cx18_card_pci_info cx18_pci_mpc718[] = {
+       { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_YUAN, 0x0718 },
+       { 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_mpc718 = {
+       .type = CX18_CARD_YUAN_MPC718,
+       .name = "Yuan MPC718",
+       .comment = "Not yet supported!\n",
+       .v4l2_capabilities = 0,
+       .hw_audio_ctrl = CX18_HW_CX23418,
+       .hw_all = CX18_HW_TUNER,
+       .video_inputs = {
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX23418_COMPOSITE7 },
+               { CX18_CARD_INPUT_SVIDEO1,    1, CX23418_SVIDEO1    },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE3 },
+       },
+       .audio_inputs = {
+               { CX18_CARD_INPUT_AUD_TUNER,
+                 CX23418_AUDIO8, 0 },
+               { CX18_CARD_INPUT_LINE_IN1,
+                 CX23418_AUDIO_SERIAL, 0 },
+       },
+       .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
+                        CX23418_AUDIO_SERIAL, 0 },
+       .tuners = {
+               /* XC3028 tuner */
+               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+       },
+       /* tuner reset */
+       .gpio_init = { .direction = 0x1000, .initial_value = 0x1000 },
+       .ddr = {
+               /* Probably Samsung K4D263238G-VC33 memory */
+               .chip_config = 0x003,
+               .refresh = 0x30c,
+               .timing1 = 0x23230b73,
+               .timing2 = 0x08,
+               .tune_lane = 0,
+               .initial_emrs = 2,
+       },
+       .pci_list = cx18_pci_mpc718,
+       .i2c = &cx18_i2c_std,
+};
+
+static const struct cx18_card *cx18_card_list[] = {
+       &cx18_card_hvr1600_esmt,
+       &cx18_card_hvr1600_samsung,
+       &cx18_card_h900,
+       &cx18_card_mpc718,
+};
+
+const struct cx18_card *cx18_get_card(u16 index)
+{
+       if (index >= ARRAY_SIZE(cx18_card_list))
+               return NULL;
+       return cx18_card_list[index];
+}
+
+int cx18_get_input(struct cx18 *cx, u16 index, struct v4l2_input *input)
+{
+       const struct cx18_card_video_input *card_input =
+               cx->card->video_inputs + index;
+       static const char * const input_strs[] = {
+               "Tuner 1",
+               "S-Video 1",
+               "S-Video 2",
+               "Composite 1",
+               "Composite 2",
+               "Composite 3"
+       };
+
+       memset(input, 0, sizeof(*input));
+       if (index >= cx->nof_inputs)
+               return -EINVAL;
+       input->index = index;
+       strlcpy(input->name, input_strs[card_input->video_type - 1],
+                       sizeof(input->name));
+       input->type = (card_input->video_type == CX18_CARD_INPUT_VID_TUNER ?
+                       V4L2_INPUT_TYPE_TUNER : V4L2_INPUT_TYPE_CAMERA);
+       input->audioset = (1 << cx->nof_audio_inputs) - 1;
+       input->std = (input->type == V4L2_INPUT_TYPE_TUNER) ?
+                               cx->tuner_std : V4L2_STD_ALL;
+       return 0;
+}
+
+int cx18_get_audio_input(struct cx18 *cx, u16 index, struct v4l2_audio *audio)
+{
+       const struct cx18_card_audio_input *aud_input =
+               cx->card->audio_inputs + index;
+       static const char * const input_strs[] = {
+               "Tuner 1",
+               "Line In 1",
+               "Line In 2"
+       };
+
+       memset(audio, 0, sizeof(*audio));
+       if (index >= cx->nof_audio_inputs)
+               return -EINVAL;
+       strlcpy(audio->name, input_strs[aud_input->audio_type - 1],
+                       sizeof(audio->name));
+       audio->index = index;
+       audio->capability = V4L2_AUDCAP_STEREO;
+       return 0;
+}
diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h
new file mode 100644 (file)
index 0000000..bca249b
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ *  cx18 functions to query card hardware
+ *
+ *  Derived from ivtv-cards.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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
+ */
+
+/* hardware flags */
+#define CX18_HW_TUNER     (1 << 0)
+#define CX18_HW_TVEEPROM  (1 << 1)
+#define CX18_HW_CS5345    (1 << 2)
+#define CX18_HW_GPIO      (1 << 3)
+#define CX18_HW_CX23418   (1 << 4)
+#define CX18_HW_DVB      (1 << 5)
+
+/* video inputs */
+#define        CX18_CARD_INPUT_VID_TUNER       1
+#define        CX18_CARD_INPUT_SVIDEO1         2
+#define        CX18_CARD_INPUT_SVIDEO2         3
+#define        CX18_CARD_INPUT_COMPOSITE1      4
+#define        CX18_CARD_INPUT_COMPOSITE2      5
+#define        CX18_CARD_INPUT_COMPOSITE3      6
+
+enum cx34180_video_input {
+       /* Composite video inputs In1-In8 */
+       CX23418_COMPOSITE1 = 1,
+       CX23418_COMPOSITE2,
+       CX23418_COMPOSITE3,
+       CX23418_COMPOSITE4,
+       CX23418_COMPOSITE5,
+       CX23418_COMPOSITE6,
+       CX23418_COMPOSITE7,
+       CX23418_COMPOSITE8,
+
+       /* S-Video inputs consist of one luma input (In1-In4) ORed with one
+          chroma input (In5-In8) */
+       CX23418_SVIDEO_LUMA1 = 0x10,
+       CX23418_SVIDEO_LUMA2 = 0x20,
+       CX23418_SVIDEO_LUMA3 = 0x30,
+       CX23418_SVIDEO_LUMA4 = 0x40,
+       CX23418_SVIDEO_CHROMA4 = 0x400,
+       CX23418_SVIDEO_CHROMA5 = 0x500,
+       CX23418_SVIDEO_CHROMA6 = 0x600,
+       CX23418_SVIDEO_CHROMA7 = 0x700,
+       CX23418_SVIDEO_CHROMA8 = 0x800,
+
+       /* S-Video aliases for common luma/chroma combinations */
+       CX23418_SVIDEO1 = 0x510,
+       CX23418_SVIDEO2 = 0x620,
+       CX23418_SVIDEO3 = 0x730,
+       CX23418_SVIDEO4 = 0x840,
+};
+
+/* audio inputs */
+#define        CX18_CARD_INPUT_AUD_TUNER       1
+#define        CX18_CARD_INPUT_LINE_IN1        2
+#define        CX18_CARD_INPUT_LINE_IN2        3
+
+#define CX18_CARD_MAX_VIDEO_INPUTS 6
+#define CX18_CARD_MAX_AUDIO_INPUTS 3
+#define CX18_CARD_MAX_TUNERS      2
+
+enum cx23418_audio_input {
+       /* Audio inputs: serial or In4-In8 */
+       CX23418_AUDIO_SERIAL,
+       CX23418_AUDIO4 = 4,
+       CX23418_AUDIO5,
+       CX23418_AUDIO6,
+       CX23418_AUDIO7,
+       CX23418_AUDIO8,
+};
+
+/* V4L2 capability aliases */
+#define CX18_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \
+                         V4L2_CAP_AUDIO | V4L2_CAP_READWRITE)
+/* | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE) not yet */
+
+struct cx18_card_video_input {
+       u8  video_type;         /* video input type */
+       u8  audio_index;        /* index in cx18_card_audio_input array */
+       u16 video_input;        /* hardware video input */
+};
+
+struct cx18_card_audio_input {
+       u8  audio_type;         /* audio input type */
+       u32 audio_input;        /* hardware audio input */
+       u16 muxer_input;        /* hardware muxer input for boards with a
+                                  multiplexer chip */
+};
+
+struct cx18_card_pci_info {
+       u16 device;
+       u16 subsystem_vendor;
+       u16 subsystem_device;
+};
+
+/* GPIO definitions */
+
+/* The mask is the set of bits used by the operation */
+
+struct cx18_gpio_init { /* set initial GPIO DIR and OUT values */
+       u16 direction;  /* DIR setting. Leave to 0 if no init is needed */
+       u16 initial_value;
+};
+
+struct cx18_card_tuner {
+       v4l2_std_id std;        /* standard for which the tuner is suitable */
+       int         tuner;      /* tuner ID (from tuner.h) */
+};
+
+struct cx18_card_tuner_i2c {
+       unsigned short radio[2];/* radio tuner i2c address to probe */
+       unsigned short demod[2];/* demodulator i2c address to probe */
+       unsigned short tv[4];   /* tv tuner i2c addresses to probe */
+};
+
+struct cx18_ddr {              /* DDR config data */
+       u32 chip_config;
+       u32 refresh;
+       u32 timing1;
+       u32 timing2;
+       u32 tune_lane;
+       u32 initial_emrs;
+};
+
+/* for card information/parameters */
+struct cx18_card {
+       int type;
+       char *name;
+       char *comment;
+       u32 v4l2_capabilities;
+       u32 hw_audio_ctrl;      /* hardware used for the V4L2 controls (only
+                                  1 dev allowed) */
+       u32 hw_muxer;           /* hardware used to multiplex audio input */
+       u32 hw_all;             /* all hardware used by the board */
+       struct cx18_card_video_input video_inputs[CX18_CARD_MAX_VIDEO_INPUTS];
+       struct cx18_card_audio_input audio_inputs[CX18_CARD_MAX_AUDIO_INPUTS];
+       struct cx18_card_audio_input radio_input;
+
+       /* GPIO card-specific settings */
+       struct cx18_gpio_init           gpio_init;
+
+       struct cx18_card_tuner tuners[CX18_CARD_MAX_TUNERS];
+       struct cx18_card_tuner_i2c *i2c;
+
+       struct cx18_ddr ddr;
+
+       /* list of device and subsystem vendor/devices that
+          correspond to this card type. */
+       const struct cx18_card_pci_info *pci_list;
+};
+
+int cx18_get_input(struct cx18 *cx, u16 index, struct v4l2_input *input);
+int cx18_get_audio_input(struct cx18 *cx, u16 index, struct v4l2_audio *input);
+const struct cx18_card *cx18_get_card(u16 index);
diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c
new file mode 100644 (file)
index 0000000..2bdac5e
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ *  cx18 ioctl control functions
+ *
+ *  Derived from ivtv-controls.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 "cx18-driver.h"
+#include "cx18-av-core.h"
+#include "cx18-cards.h"
+#include "cx18-ioctl.h"
+#include "cx18-audio.h"
+#include "cx18-i2c.h"
+#include "cx18-mailbox.h"
+#include "cx18-controls.h"
+
+static const u32 user_ctrls[] = {
+       V4L2_CID_USER_CLASS,
+       V4L2_CID_BRIGHTNESS,
+       V4L2_CID_CONTRAST,
+       V4L2_CID_SATURATION,
+       V4L2_CID_HUE,
+       V4L2_CID_AUDIO_VOLUME,
+       V4L2_CID_AUDIO_BALANCE,
+       V4L2_CID_AUDIO_BASS,
+       V4L2_CID_AUDIO_TREBLE,
+       V4L2_CID_AUDIO_MUTE,
+       V4L2_CID_AUDIO_LOUDNESS,
+       0
+};
+
+static const u32 *ctrl_classes[] = {
+       user_ctrls,
+       cx2341x_mpeg_ctrls,
+       NULL
+};
+
+static int cx18_queryctrl(struct cx18 *cx, struct v4l2_queryctrl *qctrl)
+{
+       const char *name;
+
+       CX18_DEBUG_IOCTL("VIDIOC_QUERYCTRL(%08x)\n", qctrl->id);
+
+       qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
+       if (qctrl->id == 0)
+               return -EINVAL;
+
+       switch (qctrl->id) {
+       /* Standard V4L2 controls */
+       case V4L2_CID_BRIGHTNESS:
+       case V4L2_CID_HUE:
+       case V4L2_CID_SATURATION:
+       case V4L2_CID_CONTRAST:
+               if (cx18_av_cmd(cx, VIDIOC_QUERYCTRL, qctrl))
+                       qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
+               return 0;
+
+       case V4L2_CID_AUDIO_VOLUME:
+       case V4L2_CID_AUDIO_MUTE:
+       case V4L2_CID_AUDIO_BALANCE:
+       case V4L2_CID_AUDIO_BASS:
+       case V4L2_CID_AUDIO_TREBLE:
+       case V4L2_CID_AUDIO_LOUDNESS:
+               if (cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, VIDIOC_QUERYCTRL, qctrl))
+                       qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
+               return 0;
+
+       default:
+               if (cx2341x_ctrl_query(&cx->params, qctrl))
+                       qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
+               return 0;
+       }
+       strncpy(qctrl->name, name, sizeof(qctrl->name) - 1);
+       qctrl->name[sizeof(qctrl->name) - 1] = 0;
+       return 0;
+}
+
+static int cx18_querymenu(struct cx18 *cx, struct v4l2_querymenu *qmenu)
+{
+       struct v4l2_queryctrl qctrl;
+
+       qctrl.id = qmenu->id;
+       cx18_queryctrl(cx, &qctrl);
+       return v4l2_ctrl_query_menu(qmenu, &qctrl, cx2341x_ctrl_get_menu(qmenu->id));
+}
+
+static int cx18_s_ctrl(struct cx18 *cx, struct v4l2_control *vctrl)
+{
+       s32 v = vctrl->value;
+
+       CX18_DEBUG_IOCTL("VIDIOC_S_CTRL(%08x, %x)\n", vctrl->id, v);
+
+       switch (vctrl->id) {
+               /* Standard V4L2 controls */
+       case V4L2_CID_BRIGHTNESS:
+       case V4L2_CID_HUE:
+       case V4L2_CID_SATURATION:
+       case V4L2_CID_CONTRAST:
+               return cx18_av_cmd(cx, VIDIOC_S_CTRL, vctrl);
+
+       case V4L2_CID_AUDIO_VOLUME:
+       case V4L2_CID_AUDIO_MUTE:
+       case V4L2_CID_AUDIO_BALANCE:
+       case V4L2_CID_AUDIO_BASS:
+       case V4L2_CID_AUDIO_TREBLE:
+       case V4L2_CID_AUDIO_LOUDNESS:
+               return cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, VIDIOC_S_CTRL, vctrl);
+
+       default:
+               CX18_DEBUG_IOCTL("invalid control %x\n", vctrl->id);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int cx18_g_ctrl(struct cx18 *cx, struct v4l2_control *vctrl)
+{
+       CX18_DEBUG_IOCTL("VIDIOC_G_CTRL(%08x)\n", vctrl->id);
+
+       switch (vctrl->id) {
+               /* Standard V4L2 controls */
+       case V4L2_CID_BRIGHTNESS:
+       case V4L2_CID_HUE:
+       case V4L2_CID_SATURATION:
+       case V4L2_CID_CONTRAST:
+               return cx18_av_cmd(cx, VIDIOC_G_CTRL, vctrl);
+
+       case V4L2_CID_AUDIO_VOLUME:
+       case V4L2_CID_AUDIO_MUTE:
+       case V4L2_CID_AUDIO_BALANCE:
+       case V4L2_CID_AUDIO_BASS:
+       case V4L2_CID_AUDIO_TREBLE:
+       case V4L2_CID_AUDIO_LOUDNESS:
+               return cx18_i2c_hw(cx, cx->card->hw_audio_ctrl, VIDIOC_G_CTRL, vctrl);
+       default:
+               CX18_DEBUG_IOCTL("invalid control %x\n", vctrl->id);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int cx18_setup_vbi_fmt(struct cx18 *cx, enum v4l2_mpeg_stream_vbi_fmt fmt)
+{
+       if (!(cx->v4l2_cap & V4L2_CAP_SLICED_VBI_CAPTURE))
+               return -EINVAL;
+       if (atomic_read(&cx->capturing) > 0)
+               return -EBUSY;
+
+       /* First try to allocate sliced VBI buffers if needed. */
+       if (fmt && cx->vbi.sliced_mpeg_data[0] == NULL) {
+               int i;
+
+               for (i = 0; i < CX18_VBI_FRAMES; i++) {
+                       /* Yuck, hardcoded. Needs to be a define */
+                       cx->vbi.sliced_mpeg_data[i] = kmalloc(2049, GFP_KERNEL);
+                       if (cx->vbi.sliced_mpeg_data[i] == NULL) {
+                               while (--i >= 0) {
+                                       kfree(cx->vbi.sliced_mpeg_data[i]);
+                                       cx->vbi.sliced_mpeg_data[i] = NULL;
+                               }
+                               return -ENOMEM;
+                       }
+               }
+       }
+
+       cx->vbi.insert_mpeg = fmt;
+
+       if (cx->vbi.insert_mpeg == 0)
+               return 0;
+       /* Need sliced data for mpeg insertion */
+       if (cx18_get_service_set(cx->vbi.sliced_in) == 0) {
+               if (cx->is_60hz)
+                       cx->vbi.sliced_in->service_set = V4L2_SLICED_CAPTION_525;
+               else
+                       cx->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625;
+               cx18_expand_service_set(cx->vbi.sliced_in, cx->is_50hz);
+       }
+       return 0;
+}
+
+int cx18_control_ioctls(struct cx18 *cx, unsigned int cmd, void *arg)
+{
+       struct v4l2_control ctrl;
+
+       switch (cmd) {
+       case VIDIOC_QUERYMENU:
+               CX18_DEBUG_IOCTL("VIDIOC_QUERYMENU\n");
+               return cx18_querymenu(cx, arg);
+
+       case VIDIOC_QUERYCTRL:
+               return cx18_queryctrl(cx, arg);
+
+       case VIDIOC_S_CTRL:
+               return cx18_s_ctrl(cx, arg);
+
+       case VIDIOC_G_CTRL:
+               return cx18_g_ctrl(cx, arg);
+
+       case VIDIOC_S_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *c = arg;
+
+               if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
+                       int i;
+                       int err = 0;
+
+                       for (i = 0; i < c->count; i++) {
+                               ctrl.id = c->controls[i].id;
+                               ctrl.value = c->controls[i].value;
+                               err = cx18_s_ctrl(cx, &ctrl);
+                               c->controls[i].value = ctrl.value;
+                               if (err) {
+                                       c->error_idx = i;
+                                       break;
+                               }
+                       }
+                       return err;
+               }
+               CX18_DEBUG_IOCTL("VIDIOC_S_EXT_CTRLS\n");
+               if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
+                       struct cx2341x_mpeg_params p = cx->params;
+                       int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->capturing), arg, cmd);
+
+                       if (err)
+                               return err;
+
+                       if (p.video_encoding != cx->params.video_encoding) {
+                               int is_mpeg1 = p.video_encoding ==
+                                               V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
+                               struct v4l2_format fmt;
+
+                               /* fix videodecoder resolution */
+                               fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+                               fmt.fmt.pix.width = cx->params.width / (is_mpeg1 ? 2 : 1);
+                               fmt.fmt.pix.height = cx->params.height;
+                               cx18_av_cmd(cx, VIDIOC_S_FMT, &fmt);
+                       }
+                       err = cx2341x_update(cx, cx18_api_func, &cx->params, &p);
+                       if (!err && cx->params.stream_vbi_fmt != p.stream_vbi_fmt)
+                               err = cx18_setup_vbi_fmt(cx, p.stream_vbi_fmt);
+                       cx->params = p;
+                       cx->dualwatch_stereo_mode = p.audio_properties & 0x0300;
+                       cx18_audio_set_audio_clock_freq(cx, p.audio_properties & 0x03);
+                       return err;
+               }
+               return -EINVAL;
+       }
+
+       case VIDIOC_G_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *c = arg;
+
+               if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
+                       int i;
+                       int err = 0;
+
+                       for (i = 0; i < c->count; i++) {
+                               ctrl.id = c->controls[i].id;
+                               ctrl.value = c->controls[i].value;
+                               err = cx18_g_ctrl(cx, &ctrl);
+                               c->controls[i].value = ctrl.value;
+                               if (err) {
+                                       c->error_idx = i;
+                                       break;
+                               }
+                       }
+                       return err;
+               }
+               CX18_DEBUG_IOCTL("VIDIOC_G_EXT_CTRLS\n");
+               if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG)
+                       return cx2341x_ext_ctrls(&cx->params, 0, arg, cmd);
+               return -EINVAL;
+       }
+
+       case VIDIOC_TRY_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *c = arg;
+
+               CX18_DEBUG_IOCTL("VIDIOC_TRY_EXT_CTRLS\n");
+               if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG)
+                       return cx2341x_ext_ctrls(&cx->params,
+                                       atomic_read(&cx->capturing), arg, cmd);
+               return -EINVAL;
+       }
+
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
diff --git a/drivers/media/video/cx18/cx18-controls.h b/drivers/media/video/cx18/cx18-controls.h
new file mode 100644 (file)
index 0000000..6e985cf
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  cx18 ioctl control functions
+ *
+ *  Derived from ivtv-controls.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+ *  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
+ */
+
+int cx18_control_ioctls(struct cx18 *cx, unsigned int cmd, void *arg);
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
new file mode 100644 (file)
index 0000000..8f5ed9b
--- /dev/null
@@ -0,0 +1,971 @@
+/*
+ *  cx18 driver initialization and card probing
+ *
+ *  Derived from ivtv-driver.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 "cx18-driver.h"
+#include "cx18-version.h"
+#include "cx18-cards.h"
+#include "cx18-i2c.h"
+#include "cx18-irq.h"
+#include "cx18-gpio.h"
+#include "cx18-firmware.h"
+#include "cx18-streams.h"
+#include "cx18-av-core.h"
+#include "cx18-scb.h"
+#include "cx18-mailbox.h"
+#include "cx18-ioctl.h"
+#include "tuner-xc2028.h"
+
+#include <media/tveeprom.h>
+
+
+/* var to keep track of the number of array elements in use */
+int cx18_cards_active;
+
+/* If you have already X v4l cards, then set this to X. This way
+   the device numbers stay matched. Example: you have a WinTV card
+   without radio and a Compro H900 with. Normally this would give a
+   video1 device together with a radio0 device for the Compro. By
+   setting this to 1 you ensure that radio0 is now also radio1. */
+int cx18_first_minor;
+
+/* Master variable for all cx18 info */
+struct cx18 *cx18_cards[CX18_MAX_CARDS];
+
+/* Protects cx18_cards_active */
+DEFINE_SPINLOCK(cx18_cards_lock);
+
+/* add your revision and whatnot here */
+static struct pci_device_id cx18_pci_tbl[] __devinitdata = {
+       {PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418,
+        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, cx18_pci_tbl);
+
+/* Parameter declarations */
+static int cardtype[CX18_MAX_CARDS];
+static int tuner[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
+                                    -1, -1, -1, -1, -1, -1, -1, -1,
+                                    -1, -1, -1, -1, -1, -1, -1, -1,
+                                    -1, -1, -1, -1, -1, -1, -1, -1 };
+static int radio[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
+                                    -1, -1, -1, -1, -1, -1, -1, -1,
+                                    -1, -1, -1, -1, -1, -1, -1, -1,
+                                    -1, -1, -1, -1, -1, -1, -1, -1 };
+
+static int cardtype_c = 1;
+static int tuner_c = 1;
+static int radio_c = 1;
+static char pal[] = "--";
+static char secam[] = "--";
+static char ntsc[] = "-";
+
+/* Buffers */
+static int enc_mpg_buffers = CX18_DEFAULT_ENC_MPG_BUFFERS;
+static int enc_ts_buffers = CX18_DEFAULT_ENC_TS_BUFFERS;
+static int enc_yuv_buffers = CX18_DEFAULT_ENC_YUV_BUFFERS;
+static int enc_vbi_buffers = CX18_DEFAULT_ENC_VBI_BUFFERS;
+static int enc_pcm_buffers = CX18_DEFAULT_ENC_PCM_BUFFERS;
+
+static int cx18_pci_latency = 1;
+
+int cx18_debug;
+
+module_param_array(tuner, int, &tuner_c, 0644);
+module_param_array(radio, bool, &radio_c, 0644);
+module_param_array(cardtype, int, &cardtype_c, 0644);
+module_param_string(pal, pal, sizeof(pal), 0644);
+module_param_string(secam, secam, sizeof(secam), 0644);
+module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
+module_param_named(debug, cx18_debug, int, 0644);
+module_param(cx18_pci_latency, int, 0644);
+module_param(cx18_first_minor, int, 0644);
+
+module_param(enc_mpg_buffers, int, 0644);
+module_param(enc_ts_buffers, int, 0644);
+module_param(enc_yuv_buffers, int, 0644);
+module_param(enc_vbi_buffers, int, 0644);
+module_param(enc_pcm_buffers, int, 0644);
+
+MODULE_PARM_DESC(tuner, "Tuner type selection,\n"
+                       "\t\t\tsee tuner.h for values");
+MODULE_PARM_DESC(radio,
+                "Enable or disable the radio. Use only if autodetection\n"
+                "\t\t\tfails. 0 = disable, 1 = enable");
+MODULE_PARM_DESC(cardtype,
+                "Only use this option if your card is not detected properly.\n"
+                "\t\tSpecify card type:\n"
+                "\t\t\t 1 = Hauppauge HVR 1600 (ESMT memory)\n"
+                "\t\t\t 2 = Hauppauge HVR 1600 (Samsung memory)\n"
+                "\t\t\t 3 = Compro VideoMate H900\n"
+                "\t\t\t 4 = Yuan MPC718\n"
+                "\t\t\t 0 = Autodetect (default)\n"
+                "\t\t\t-1 = Ignore this card\n\t\t");
+MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60");
+MODULE_PARM_DESC(secam, "Set SECAM standard: B, G, H, D, K, L, LC");
+MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J, K");
+MODULE_PARM_DESC(debug,
+                "Debug level (bitmask). Default: 0\n"
+                "\t\t\t  1/0x0001: warning\n"
+                "\t\t\t  2/0x0002: info\n"
+                "\t\t\t  4/0x0004: mailbox\n"
+                "\t\t\t  8/0x0008: dma\n"
+                "\t\t\t 16/0x0010: ioctl\n"
+                "\t\t\t 32/0x0020: file\n"
+                "\t\t\t 64/0x0040: i2c\n"
+                "\t\t\t128/0x0080: irq\n"
+                "\t\t\t256/0x0100: high volume\n");
+MODULE_PARM_DESC(cx18_pci_latency,
+                "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n"
+                "\t\t\tDefault: Yes");
+MODULE_PARM_DESC(enc_mpg_buffers,
+                "Encoder MPG Buffers (in MB)\n"
+                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS));
+MODULE_PARM_DESC(enc_ts_buffers,
+                "Encoder TS Buffers (in MB)\n"
+                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_TS_BUFFERS));
+MODULE_PARM_DESC(enc_yuv_buffers,
+                "Encoder YUV Buffers (in MB)\n"
+                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS));
+MODULE_PARM_DESC(enc_vbi_buffers,
+                "Encoder VBI Buffers (in MB)\n"
+                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_VBI_BUFFERS));
+MODULE_PARM_DESC(enc_pcm_buffers,
+                "Encoder PCM buffers (in MB)\n"
+                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS));
+
+MODULE_PARM_DESC(cx18_first_minor, "Set minor assigned to first card");
+
+MODULE_AUTHOR("Hans Verkuil");
+MODULE_DESCRIPTION("CX23418 driver");
+MODULE_SUPPORTED_DEVICE("CX23418 MPEG2 encoder");
+MODULE_LICENSE("GPL");
+
+MODULE_VERSION(CX18_VERSION);
+
+int cx18_waitq(wait_queue_head_t *waitq)
+{
+       DEFINE_WAIT(wait);
+
+       prepare_to_wait(waitq, &wait, TASK_INTERRUPTIBLE);
+       schedule();
+       finish_wait(waitq, &wait);
+       return signal_pending(current) ? -EINTR : 0;
+}
+
+/* Generic utility functions */
+int cx18_msleep_timeout(unsigned int msecs, int intr)
+{
+       int timeout = msecs_to_jiffies(msecs);
+       int sig;
+
+       do {
+               set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+               timeout = schedule_timeout(timeout);
+               sig = intr ? signal_pending(current) : 0;
+       } while (!sig && timeout);
+       return sig;
+}
+
+/* Release ioremapped memory */
+static void cx18_iounmap(struct cx18 *cx)
+{
+       if (cx == NULL)
+               return;
+
+       /* Release io memory */
+       if (cx->enc_mem != NULL) {
+               CX18_DEBUG_INFO("releasing enc_mem\n");
+               iounmap(cx->enc_mem);
+               cx->enc_mem = NULL;
+       }
+}
+
+/* Hauppauge card? get values from tveeprom */
+void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv)
+{
+       u8 eedata[256];
+
+       cx->i2c_client[0].addr = 0xA0 >> 1;
+       tveeprom_read(&cx->i2c_client[0], eedata, sizeof(eedata));
+       tveeprom_hauppauge_analog(&cx->i2c_client[0], tv, eedata);
+}
+
+static void cx18_process_eeprom(struct cx18 *cx)
+{
+       struct tveeprom tv;
+
+       cx18_read_eeprom(cx, &tv);
+
+       /* Many thanks to Steven Toth from Hauppauge for providing the
+          model numbers */
+       switch (tv.model) {
+       case 74000 ... 74099:
+               cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
+               break;
+       case 74700 ... 74799:
+               cx->card = cx18_get_card(CX18_CARD_HVR_1600_SAMSUNG);
+               break;
+       case 0:
+               CX18_ERR("Invalid EEPROM\n");
+               return;
+       default:
+               CX18_ERR("Unknown model %d, defaulting to HVR-1600\n", tv.model);
+               cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
+               break;
+       }
+
+       cx->v4l2_cap = cx->card->v4l2_capabilities;
+       cx->card_name = cx->card->name;
+       cx->card_i2c = cx->card->i2c;
+
+       CX18_INFO("Autodetected %s\n", cx->card_name);
+
+       if (tv.tuner_type == TUNER_ABSENT)
+               CX18_ERR("tveeprom cannot autodetect tuner!");
+
+       if (cx->options.tuner == -1)
+               cx->options.tuner = tv.tuner_type;
+       if (cx->options.radio == -1)
+               cx->options.radio = (tv.has_radio != 0);
+
+       if (cx->std != 0)
+               /* user specified tuner standard */
+               return;
+
+       /* autodetect tuner standard */
+       if (tv.tuner_formats & V4L2_STD_PAL) {
+               CX18_DEBUG_INFO("PAL tuner detected\n");
+               cx->std |= V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
+       } else if (tv.tuner_formats & V4L2_STD_NTSC) {
+               CX18_DEBUG_INFO("NTSC tuner detected\n");
+               cx->std |= V4L2_STD_NTSC_M;
+       } else if (tv.tuner_formats & V4L2_STD_SECAM) {
+               CX18_DEBUG_INFO("SECAM tuner detected\n");
+               cx->std |= V4L2_STD_SECAM_L;
+       } else {
+               CX18_INFO("No tuner detected, default to NTSC-M\n");
+               cx->std |= V4L2_STD_NTSC_M;
+       }
+}
+
+static v4l2_std_id cx18_parse_std(struct cx18 *cx)
+{
+       switch (pal[0]) {
+       case '6':
+               return V4L2_STD_PAL_60;
+       case 'b':
+       case 'B':
+       case 'g':
+       case 'G':
+               return V4L2_STD_PAL_BG;
+       case 'h':
+       case 'H':
+               return V4L2_STD_PAL_H;
+       case 'n':
+       case 'N':
+               if (pal[1] == 'c' || pal[1] == 'C')
+                       return V4L2_STD_PAL_Nc;
+               return V4L2_STD_PAL_N;
+       case 'i':
+       case 'I':
+               return V4L2_STD_PAL_I;
+       case 'd':
+       case 'D':
+       case 'k':
+       case 'K':
+               return V4L2_STD_PAL_DK;
+       case 'M':
+       case 'm':
+               return V4L2_STD_PAL_M;
+       case '-':
+               break;
+       default:
+               CX18_WARN("pal= argument not recognised\n");
+               return 0;
+       }
+
+       switch (secam[0]) {
+       case 'b':
+       case 'B':
+       case 'g':
+       case 'G':
+       case 'h':
+       case 'H':
+               return V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
+       case 'd':
+       case 'D':
+       case 'k':
+       case 'K':
+               return V4L2_STD_SECAM_DK;
+       case 'l':
+       case 'L':
+               if (secam[1] == 'C' || secam[1] == 'c')
+                       return V4L2_STD_SECAM_LC;
+               return V4L2_STD_SECAM_L;
+       case '-':
+               break;
+       default:
+               CX18_WARN("secam= argument not recognised\n");
+               return 0;
+       }
+
+       switch (ntsc[0]) {
+       case 'm':
+       case 'M':
+               return V4L2_STD_NTSC_M;
+       case 'j':
+       case 'J':
+               return V4L2_STD_NTSC_M_JP;
+       case 'k':
+       case 'K':
+               return V4L2_STD_NTSC_M_KR;
+       case '-':
+               break;
+       default:
+               CX18_WARN("ntsc= argument not recognised\n");
+               return 0;
+       }
+
+       /* no match found */
+       return 0;
+}
+
+static void cx18_process_options(struct cx18 *cx)
+{
+       int i, j;
+
+       cx->options.megabytes[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers;
+       cx->options.megabytes[CX18_ENC_STREAM_TYPE_TS] = enc_ts_buffers;
+       cx->options.megabytes[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_buffers;
+       cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] = enc_vbi_buffers;
+       cx->options.megabytes[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_buffers;
+       cx->options.cardtype = cardtype[cx->num];
+       cx->options.tuner = tuner[cx->num];
+       cx->options.radio = radio[cx->num];
+
+       cx->std = cx18_parse_std(cx);
+       if (cx->options.cardtype == -1) {
+               CX18_INFO("Ignore card\n");
+               return;
+       }
+       cx->card = cx18_get_card(cx->options.cardtype - 1);
+       if (cx->card)
+               CX18_INFO("User specified %s card\n", cx->card->name);
+       else if (cx->options.cardtype != 0)
+               CX18_ERR("Unknown user specified type, trying to autodetect card\n");
+       if (cx->card == NULL) {
+               if (cx->dev->subsystem_vendor == CX18_PCI_ID_HAUPPAUGE) {
+                       cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
+                       CX18_INFO("Autodetected Hauppauge card\n");
+               }
+       }
+       if (cx->card == NULL) {
+               for (i = 0; (cx->card = cx18_get_card(i)); i++) {
+                       if (cx->card->pci_list == NULL)
+                               continue;
+                       for (j = 0; cx->card->pci_list[j].device; j++) {
+                               if (cx->dev->device !=
+                                   cx->card->pci_list[j].device)
+                                       continue;
+                               if (cx->dev->subsystem_vendor !=
+                                   cx->card->pci_list[j].subsystem_vendor)
+                                       continue;
+                               if (cx->dev->subsystem_device !=
+                                   cx->card->pci_list[j].subsystem_device)
+                                       continue;
+                               CX18_INFO("Autodetected %s card\n", cx->card->name);
+                               goto done;
+                       }
+               }
+       }
+done:
+
+       if (cx->card == NULL) {
+               cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
+               CX18_ERR("Unknown card: vendor/device: %04x/%04x\n",
+                    cx->dev->vendor, cx->dev->device);
+               CX18_ERR("              subsystem vendor/device: %04x/%04x\n",
+                    cx->dev->subsystem_vendor, cx->dev->subsystem_device);
+               CX18_ERR("Defaulting to %s card\n", cx->card->name);
+               CX18_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n");
+               CX18_ERR("card you have to the ivtv-devel mailinglist (www.ivtvdriver.org)\n");
+               CX18_ERR("Prefix your subject line with [UNKNOWN CX18 CARD].\n");
+       }
+       cx->v4l2_cap = cx->card->v4l2_capabilities;
+       cx->card_name = cx->card->name;
+       cx->card_i2c = cx->card->i2c;
+}
+
+/* Precondition: the cx18 structure has been memset to 0. Only
+   the dev and num fields have been filled in.
+   No assumptions on the card type may be made here (see cx18_init_struct2
+   for that).
+ */
+static int __devinit cx18_init_struct1(struct cx18 *cx)
+{
+       cx->base_addr = pci_resource_start(cx->dev, 0);
+
+       mutex_init(&cx->serialize_lock);
+       mutex_init(&cx->i2c_bus_lock[0]);
+       mutex_init(&cx->i2c_bus_lock[1]);
+
+       spin_lock_init(&cx->lock);
+       spin_lock_init(&cx->dma_reg_lock);
+
+       /* start counting open_id at 1 */
+       cx->open_id = 1;
+
+       /* Initial settings */
+       cx2341x_fill_defaults(&cx->params);
+       cx->temporal_strength = cx->params.video_temporal_filter;
+       cx->spatial_strength = cx->params.video_spatial_filter;
+       cx->filter_mode = cx->params.video_spatial_filter_mode |
+               (cx->params.video_temporal_filter_mode << 1) |
+               (cx->params.video_median_filter_type << 2);
+       cx->params.port = CX2341X_PORT_MEMORY;
+       cx->params.capabilities = CX2341X_CAP_HAS_SLICED_VBI;
+       init_waitqueue_head(&cx->cap_w);
+       init_waitqueue_head(&cx->mb_apu_waitq);
+       init_waitqueue_head(&cx->mb_cpu_waitq);
+       init_waitqueue_head(&cx->mb_epu_waitq);
+       init_waitqueue_head(&cx->mb_hpu_waitq);
+       init_waitqueue_head(&cx->dma_waitq);
+
+       /* VBI */
+       cx->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
+       cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced;
+       cx->vbi.raw_size = 1456;
+       cx->vbi.raw_decoder_line_size = 1456;
+       cx->vbi.raw_decoder_sav_odd_field = 0x20;
+       cx->vbi.raw_decoder_sav_even_field = 0x60;
+       cx->vbi.sliced_decoder_line_size = 272;
+       cx->vbi.sliced_decoder_sav_odd_field = 0xB0;
+       cx->vbi.sliced_decoder_sav_even_field = 0xF0;
+       return 0;
+}
+
+/* Second initialization part. Here the card type has been
+   autodetected. */
+static void __devinit cx18_init_struct2(struct cx18 *cx)
+{
+       int i;
+
+       for (i = 0; i < CX18_CARD_MAX_VIDEO_INPUTS; i++)
+               if (cx->card->video_inputs[i].video_type == 0)
+                       break;
+       cx->nof_inputs = i;
+       for (i = 0; i < CX18_CARD_MAX_AUDIO_INPUTS; i++)
+               if (cx->card->audio_inputs[i].audio_type == 0)
+                       break;
+       cx->nof_audio_inputs = i;
+
+       /* Find tuner input */
+       for (i = 0; i < cx->nof_inputs; i++) {
+               if (cx->card->video_inputs[i].video_type ==
+                               CX18_CARD_INPUT_VID_TUNER)
+                       break;
+       }
+       if (i == cx->nof_inputs)
+               i = 0;
+       cx->active_input = i;
+       cx->audio_input = cx->card->video_inputs[i].audio_index;
+       cx->av_state.vid_input = CX18_AV_COMPOSITE7;
+       cx->av_state.aud_input = CX18_AV_AUDIO8;
+       cx->av_state.audclk_freq = 48000;
+       cx->av_state.audmode = V4L2_TUNER_MODE_LANG1;
+       cx->av_state.vbi_line_offset = 8;
+}
+
+static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev,
+                         const struct pci_device_id *pci_id)
+{
+       u16 cmd;
+       unsigned char pci_latency;
+
+       CX18_DEBUG_INFO("Enabling pci device\n");
+
+       if (pci_enable_device(dev)) {
+               CX18_ERR("Can't enable device %d!\n", cx->num);
+               return -EIO;
+       }
+       if (pci_set_dma_mask(dev, 0xffffffff)) {
+               CX18_ERR("No suitable DMA available on card %d.\n", cx->num);
+               return -EIO;
+       }
+       if (!request_mem_region(cx->base_addr, CX18_MEM_SIZE, "cx18 encoder")) {
+               CX18_ERR("Cannot request encoder memory region on card %d.\n", cx->num);
+               return -EIO;
+       }
+
+       /* Check for bus mastering */
+       pci_read_config_word(dev, PCI_COMMAND, &cmd);
+       cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+       pci_write_config_word(dev, PCI_COMMAND, cmd);
+
+       pci_read_config_byte(dev, PCI_CLASS_REVISION, &cx->card_rev);
+       pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency);
+
+       if (pci_latency < 64 && cx18_pci_latency) {
+               CX18_INFO("Unreasonably low latency timer, "
+                              "setting to 64 (was %d)\n", pci_latency);
+               pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
+               pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency);
+       }
+       /* This config space value relates to DMA latencies. The
+          default value 0x8080 is too low however and will lead
+          to DMA errors. 0xffff is the max value which solves
+          these problems. */
+       pci_write_config_dword(dev, 0x40, 0xffff);
+
+       CX18_DEBUG_INFO("cx%d (rev %d) at %02x:%02x.%x, "
+                  "irq: %d, latency: %d, memory: 0x%lx\n",
+                  cx->dev->device, cx->card_rev, dev->bus->number,
+                  PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
+                  cx->dev->irq, pci_latency, (unsigned long)cx->base_addr);
+
+       return 0;
+}
+
+static u32 cx18_request_module(struct cx18 *cx, u32 hw,
+               const char *name, u32 id)
+{
+       if ((hw & id) == 0)
+               return hw;
+       if (request_module(name) != 0) {
+               CX18_ERR("Failed to load module %s\n", name);
+               return hw & ~id;
+       }
+       CX18_DEBUG_INFO("Loaded module %s\n", name);
+       return hw;
+}
+
+static void cx18_load_and_init_modules(struct cx18 *cx)
+{
+       u32 hw = cx->card->hw_all;
+       int i;
+
+       /* load modules */
+#ifndef CONFIG_MEDIA_TUNER
+       hw = cx18_request_module(cx, hw, "tuner", CX18_HW_TUNER);
+#endif
+#ifndef CONFIG_VIDEO_CS5345
+       hw = cx18_request_module(cx, hw, "cs5345", CX18_HW_CS5345);
+#endif
+
+       /* check which i2c devices are actually found */
+       for (i = 0; i < 32; i++) {
+               u32 device = 1 << i;
+
+               if (!(device & hw))
+                       continue;
+               if (device == CX18_HW_GPIO || device == CX18_HW_TVEEPROM ||
+                   device == CX18_HW_CX23418 || device == CX18_HW_DVB) {
+                       /* These 'devices' do not use i2c probing */
+                       cx->hw_flags |= device;
+                       continue;
+               }
+               cx18_i2c_register(cx, i);
+               if (cx18_i2c_hw_addr(cx, device) > 0)
+                       cx->hw_flags |= device;
+       }
+
+       hw = cx->hw_flags;
+}
+
+static int __devinit cx18_probe(struct pci_dev *dev,
+                               const struct pci_device_id *pci_id)
+{
+       int retval = 0;
+       int vbi_buf_size;
+       u32 devtype;
+       struct cx18 *cx;
+
+       spin_lock(&cx18_cards_lock);
+
+       /* Make sure we've got a place for this card */
+       if (cx18_cards_active == CX18_MAX_CARDS) {
+               printk(KERN_ERR "cx18:  Maximum number of cards detected (%d).\n",
+                             cx18_cards_active);
+               spin_unlock(&cx18_cards_lock);
+               return -ENOMEM;
+       }
+
+       cx = kzalloc(sizeof(struct cx18), GFP_ATOMIC);
+       if (cx == 0) {
+               spin_unlock(&cx18_cards_lock);
+               return -ENOMEM;
+       }
+       cx18_cards[cx18_cards_active] = cx;
+       cx->dev = dev;
+       cx->num = cx18_cards_active++;
+       snprintf(cx->name, sizeof(cx->name) - 1, "cx18-%d", cx->num);
+       CX18_INFO("Initializing card #%d\n", cx->num);
+
+       spin_unlock(&cx18_cards_lock);
+
+       cx18_process_options(cx);
+       if (cx->options.cardtype == -1) {
+               retval = -ENODEV;
+               goto err;
+       }
+       if (cx18_init_struct1(cx)) {
+               retval = -ENOMEM;
+               goto err;
+       }
+
+       CX18_DEBUG_INFO("base addr: 0x%08x\n", cx->base_addr);
+
+       /* PCI Device Setup */
+       retval = cx18_setup_pci(cx, dev, pci_id);
+       if (retval != 0) {
+               if (retval == -EIO)
+                       goto free_workqueue;
+               else if (retval == -ENXIO)
+                       goto free_mem;
+       }
+       /* save cx in the pci struct for later use */
+       pci_set_drvdata(dev, cx);
+
+       /* map io memory */
+       CX18_DEBUG_INFO("attempting ioremap at 0x%08x len 0x%08x\n",
+                  cx->base_addr + CX18_MEM_OFFSET, CX18_MEM_SIZE);
+       cx->enc_mem = ioremap_nocache(cx->base_addr + CX18_MEM_OFFSET,
+                                      CX18_MEM_SIZE);
+       if (!cx->enc_mem) {
+               CX18_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n");
+               CX18_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n");
+               retval = -ENOMEM;
+               goto free_mem;
+       }
+       cx->reg_mem = cx->enc_mem + CX18_REG_OFFSET;
+       devtype = read_reg(0xC72028);
+       switch (devtype & 0xff000000) {
+       case 0xff000000:
+               CX18_INFO("cx23418 revision %08x (A)\n", devtype);
+               break;
+       case 0x01000000:
+               CX18_INFO("cx23418 revision %08x (B)\n", devtype);
+               break;
+       default:
+               CX18_INFO("cx23418 revision %08x (Unknown)\n", devtype);
+               break;
+       }
+
+       cx18_init_power(cx, 1);
+       cx18_init_memory(cx);
+
+       cx->scb = (struct cx18_scb *)(cx->enc_mem + SCB_OFFSET);
+       cx18_init_scb(cx);
+
+       cx18_gpio_init(cx);
+
+       /* active i2c  */
+       CX18_DEBUG_INFO("activating i2c...\n");
+       if (init_cx18_i2c(cx)) {
+               CX18_ERR("Could not initialize i2c\n");
+               goto free_map;
+       }
+
+       CX18_DEBUG_INFO("Active card count: %d.\n", cx18_cards_active);
+
+       if (cx->card->hw_all & CX18_HW_TVEEPROM) {
+               /* Based on the model number the cardtype may be changed.
+                  The PCI IDs are not always reliable. */
+               cx18_process_eeprom(cx);
+       }
+       if (cx->card->comment)
+               CX18_INFO("%s", cx->card->comment);
+       if (cx->card->v4l2_capabilities == 0) {
+               retval = -ENODEV;
+               goto free_i2c;
+       }
+       cx18_init_memory(cx);
+
+       /* Register IRQ */
+       retval = request_irq(cx->dev->irq, cx18_irq_handler,
+                            IRQF_SHARED | IRQF_DISABLED, cx->name, (void *)cx);
+       if (retval) {
+               CX18_ERR("Failed to register irq %d\n", retval);
+               goto free_i2c;
+       }
+
+       if (cx->std == 0)
+               cx->std = V4L2_STD_NTSC_M;
+
+       if (cx->options.tuner == -1) {
+               int i;
+
+               for (i = 0; i < CX18_CARD_MAX_TUNERS; i++) {
+                       if ((cx->std & cx->card->tuners[i].std) == 0)
+                               continue;
+                       cx->options.tuner = cx->card->tuners[i].tuner;
+                       break;
+               }
+       }
+       /* if no tuner was found, then pick the first tuner in the card list */
+       if (cx->options.tuner == -1 && cx->card->tuners[0].std) {
+               cx->std = cx->card->tuners[0].std;
+               cx->options.tuner = cx->card->tuners[0].tuner;
+       }
+       if (cx->options.radio == -1)
+               cx->options.radio = (cx->card->radio_input.audio_type != 0);
+
+       /* The card is now fully identified, continue with card-specific
+          initialization. */
+       cx18_init_struct2(cx);
+
+       cx18_load_and_init_modules(cx);
+
+       if (cx->std & V4L2_STD_525_60) {
+               cx->is_60hz = 1;
+               cx->is_out_60hz = 1;
+       } else {
+               cx->is_50hz = 1;
+               cx->is_out_50hz = 1;
+       }
+       cx->params.video_gop_size = cx->is_60hz ? 15 : 12;
+
+       cx->stream_buf_size[CX18_ENC_STREAM_TYPE_MPG] = 0x08000;
+       cx->stream_buf_size[CX18_ENC_STREAM_TYPE_TS] = 0x08000;
+       cx->stream_buf_size[CX18_ENC_STREAM_TYPE_PCM] = 0x01200;
+       cx->stream_buf_size[CX18_ENC_STREAM_TYPE_YUV] = 0x20000;
+       vbi_buf_size = cx->vbi.raw_size * (cx->is_60hz ? 24 : 36) / 2;
+       cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_buf_size;
+
+       if (cx->options.radio > 0)
+               cx->v4l2_cap |= V4L2_CAP_RADIO;
+
+       retval = cx18_streams_setup(cx);
+       if (retval) {
+               CX18_ERR("Error %d setting up streams\n", retval);
+               goto free_irq;
+       }
+       retval = cx18_streams_register(cx);
+       if (retval) {
+               CX18_ERR("Error %d registering devices\n", retval);
+               goto free_streams;
+       }
+
+       if (cx->options.tuner > -1) {
+               struct tuner_setup setup;
+
+               setup.addr = ADDR_UNSET;
+               setup.type = cx->options.tuner;
+               setup.mode_mask = T_ANALOG_TV;  /* matches TV tuners */
+               setup.tuner_callback = (setup.type == TUNER_XC2028) ?
+                       cx18_reset_tuner_gpio : NULL;
+               cx18_call_i2c_clients(cx, TUNER_SET_TYPE_ADDR, &setup);
+               if (setup.type == TUNER_XC2028) {
+                       static struct xc2028_ctrl ctrl = {
+                               .fname = XC2028_DEFAULT_FIRMWARE,
+                               .max_len = 64,
+                       };
+                       struct v4l2_priv_tun_config cfg = {
+                               .tuner = cx->options.tuner,
+                               .priv = &ctrl,
+                       };
+                       cx18_call_i2c_clients(cx, TUNER_SET_CONFIG, &cfg);
+               }
+       }
+
+       /* The tuner is fixed to the standard. The other inputs (e.g. S-Video)
+          are not. */
+       cx->tuner_std = cx->std;
+
+       cx18_init_on_first_open(cx);
+
+       CX18_INFO("Initialized card #%d: %s\n", cx->num, cx->card_name);
+
+       return 0;
+
+free_streams:
+       cx18_streams_cleanup(cx);
+free_irq:
+       free_irq(cx->dev->irq, (void *)cx);
+free_i2c:
+       exit_cx18_i2c(cx);
+free_map:
+       cx18_iounmap(cx);
+free_mem:
+       release_mem_region(cx->base_addr, CX18_MEM_SIZE);
+free_workqueue:
+err:
+       if (retval == 0)
+               retval = -ENODEV;
+       CX18_ERR("Error %d on initialization\n", retval);
+
+       kfree(cx18_cards[cx18_cards_active]);
+       cx18_cards[cx18_cards_active] = NULL;
+       return retval;
+}
+
+int cx18_init_on_first_open(struct cx18 *cx)
+{
+       int video_input;
+       int fw_retry_count = 3;
+       struct v4l2_frequency vf;
+
+       if (test_bit(CX18_F_I_FAILED, &cx->i_flags))
+               return -ENXIO;
+
+       if (test_and_set_bit(CX18_F_I_INITED, &cx->i_flags))
+               return 0;
+
+       while (--fw_retry_count > 0) {
+               /* load firmware */
+               if (cx18_firmware_init(cx) == 0)
+                       break;
+               if (fw_retry_count > 1)
+                       CX18_WARN("Retry loading firmware\n");
+       }
+
+       if (fw_retry_count == 0) {
+               set_bit(CX18_F_I_FAILED, &cx->i_flags);
+               return -ENXIO;
+       }
+       set_bit(CX18_F_I_LOADED_FW, &cx->i_flags);
+
+       /* Init the firmware twice to work around a silicon bug
+        * transport related. */
+
+       fw_retry_count = 3;
+       while (--fw_retry_count > 0) {
+               /* load firmware */
+               if (cx18_firmware_init(cx) == 0)
+                       break;
+               if (fw_retry_count > 1)
+                       CX18_WARN("Retry loading firmware\n");
+       }
+
+       if (fw_retry_count == 0) {
+               set_bit(CX18_F_I_FAILED, &cx->i_flags);
+               return -ENXIO;
+       }
+
+       vf.tuner = 0;
+       vf.type = V4L2_TUNER_ANALOG_TV;
+       vf.frequency = 6400; /* the tuner 'baseline' frequency */
+
+       /* Set initial frequency. For PAL/SECAM broadcasts no
+          'default' channel exists AFAIK. */
+       if (cx->std == V4L2_STD_NTSC_M_JP)
+               vf.frequency = 1460;    /* ch. 1 91250*16/1000 */
+       else if (cx->std & V4L2_STD_NTSC_M)
+               vf.frequency = 1076;    /* ch. 4 67250*16/1000 */
+
+       video_input = cx->active_input;
+       cx->active_input++;     /* Force update of input */
+       cx18_v4l2_ioctls(cx, NULL, VIDIOC_S_INPUT, &video_input);
+
+       /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code
+          in one place. */
+       cx->std++;              /* Force full standard initialization */
+       cx18_v4l2_ioctls(cx, NULL, VIDIOC_S_STD, &cx->tuner_std);
+       cx18_v4l2_ioctls(cx, NULL, VIDIOC_S_FREQUENCY, &vf);
+       return 0;
+}
+
+static void cx18_remove(struct pci_dev *pci_dev)
+{
+       struct cx18 *cx = pci_get_drvdata(pci_dev);
+
+       CX18_DEBUG_INFO("Removing Card #%d\n", cx->num);
+
+       /* Stop all captures */
+       CX18_DEBUG_INFO("Stopping all streams\n");
+       if (atomic_read(&cx->capturing) > 0)
+               cx18_stop_all_captures(cx);
+
+       /* Interrupts */
+       sw1_irq_disable(IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
+       sw2_irq_disable(IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
+
+       cx18_halt_firmware(cx);
+
+       cx18_streams_cleanup(cx);
+
+       exit_cx18_i2c(cx);
+
+       free_irq(cx->dev->irq, (void *)cx);
+
+       if (cx->dev)
+               cx18_iounmap(cx);
+
+       release_mem_region(cx->base_addr, CX18_MEM_SIZE);
+
+       pci_disable_device(cx->dev);
+
+       CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num);
+}
+
+/* define a pci_driver for card detection */
+static struct pci_driver cx18_pci_driver = {
+      .name =     "cx18",
+      .id_table = cx18_pci_tbl,
+      .probe =    cx18_probe,
+      .remove =   cx18_remove,
+};
+
+static int module_start(void)
+{
+       printk(KERN_INFO "cx18:  Start initialization, version %s\n", CX18_VERSION);
+
+       memset(cx18_cards, 0, sizeof(cx18_cards));
+
+       /* Validate parameters */
+       if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) {
+               printk(KERN_ERR "cx18:  Exiting, ivtv_first_minor must be between 0 and %d\n",
+                    CX18_MAX_CARDS - 1);
+               return -1;
+       }
+
+       if (cx18_debug < 0 || cx18_debug > 511) {
+               cx18_debug = 0;
+               printk(KERN_INFO "cx18:   Debug value must be >= 0 and <= 511!\n");
+       }
+
+       if (pci_register_driver(&cx18_pci_driver)) {
+               printk(KERN_ERR "cx18:   Error detecting PCI card\n");
+               return -ENODEV;
+       }
+       printk(KERN_INFO "cx18:  End initialization\n");
+       return 0;
+}
+
+static void module_cleanup(void)
+{
+       int i;
+
+       pci_unregister_driver(&cx18_pci_driver);
+
+       for (i = 0; i < cx18_cards_active; i++) {
+               if (cx18_cards[i] == NULL)
+                       continue;
+               kfree(cx18_cards[i]);
+       }
+}
+
+module_init(module_start);
+module_exit(module_cleanup);
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
new file mode 100644 (file)
index 0000000..2ee9391
--- /dev/null
@@ -0,0 +1,500 @@
+/*
+ *  cx18 driver internal defines and structures
+ *
+ *  Derived from ivtv-driver.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 CX18_DRIVER_H
+#define CX18_DRIVER_H
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/list.h>
+#include <linux/unistd.h>
+#include <linux/byteorder/swab.h>
+#include <linux/pagemap.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+
+#include <linux/dvb/video.h>
+#include <linux/dvb/audio.h>
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+#include "cx18-mailbox.h"
+#include "cx18-av-core.h"
+#include "cx23418.h"
+
+/* DVB */
+#include "demux.h"
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+#include "dvbdev.h"
+
+#ifndef CONFIG_PCI
+#  error "This driver requires kernel PCI support."
+#endif
+
+#define CX18_MEM_OFFSET        0x00000000
+#define CX18_MEM_SIZE  0x04000000
+#define CX18_REG_OFFSET        0x02000000
+
+/* Maximum cx18 driver instances. */
+#define CX18_MAX_CARDS 32
+
+/* Supported cards */
+#define CX18_CARD_HVR_1600_ESMT              0 /* Hauppauge HVR 1600 (ESMT memory) */
+#define CX18_CARD_HVR_1600_SAMSUNG    1        /* Hauppauge HVR 1600 (Samsung memory) */
+#define CX18_CARD_COMPRO_H900        2 /* Compro VideoMate H900 */
+#define CX18_CARD_YUAN_MPC718        3 /* Yuan MPC718 */
+#define CX18_CARD_LAST                       3
+
+#define CX18_ENC_STREAM_TYPE_MPG  0
+#define CX18_ENC_STREAM_TYPE_TS   1
+#define CX18_ENC_STREAM_TYPE_YUV  2
+#define CX18_ENC_STREAM_TYPE_VBI  3
+#define CX18_ENC_STREAM_TYPE_PCM  4
+#define CX18_ENC_STREAM_TYPE_IDX  5
+#define CX18_ENC_STREAM_TYPE_RAD  6
+#define CX18_MAX_STREAMS         7
+
+/* system vendor and device IDs */
+#define PCI_VENDOR_ID_CX      0x14f1
+#define PCI_DEVICE_ID_CX23418 0x5b7a
+
+/* subsystem vendor ID */
+#define CX18_PCI_ID_HAUPPAUGE          0x0070
+#define CX18_PCI_ID_COMPRO             0x185b
+#define CX18_PCI_ID_YUAN               0x12ab
+
+/* ======================================================================== */
+/* ========================== START USER SETTABLE DMA VARIABLES =========== */
+/* ======================================================================== */
+
+/* DMA Buffers, Default size in MB allocated */
+#define CX18_DEFAULT_ENC_TS_BUFFERS  1
+#define CX18_DEFAULT_ENC_MPG_BUFFERS 2
+#define CX18_DEFAULT_ENC_IDX_BUFFERS 1
+#define CX18_DEFAULT_ENC_YUV_BUFFERS 2
+#define CX18_DEFAULT_ENC_VBI_BUFFERS 1
+#define CX18_DEFAULT_ENC_PCM_BUFFERS 1
+
+/* i2c stuff */
+#define I2C_CLIENTS_MAX 16
+
+/* debugging */
+
+/* Flag to turn on high volume debugging */
+#define CX18_DBGFLG_WARN  (1 << 0)
+#define CX18_DBGFLG_INFO  (1 << 1)
+#define CX18_DBGFLG_API   (1 << 2)
+#define CX18_DBGFLG_DMA   (1 << 3)
+#define CX18_DBGFLG_IOCTL (1 << 4)
+#define CX18_DBGFLG_FILE  (1 << 5)
+#define CX18_DBGFLG_I2C   (1 << 6)
+#define CX18_DBGFLG_IRQ   (1 << 7)
+/* Flag to turn on high volume debugging */
+#define CX18_DBGFLG_HIGHVOL (1 << 8)
+
+/* NOTE: extra space before comma in 'cx->num , ## args' is required for
+   gcc-2.95, otherwise it won't compile. */
+#define CX18_DEBUG(x, type, fmt, args...) \
+       do { \
+               if ((x) & cx18_debug) \
+                       printk(KERN_INFO "cx18-%d " type ": " fmt, cx->num , ## args); \
+       } while (0)
+#define CX18_DEBUG_WARN(fmt, args...)  CX18_DEBUG(CX18_DBGFLG_WARN, "warning", fmt , ## args)
+#define CX18_DEBUG_INFO(fmt, args...)  CX18_DEBUG(CX18_DBGFLG_INFO, "info", fmt , ## args)
+#define CX18_DEBUG_API(fmt, args...)   CX18_DEBUG(CX18_DBGFLG_API, "api", fmt , ## args)
+#define CX18_DEBUG_DMA(fmt, args...)   CX18_DEBUG(CX18_DBGFLG_DMA, "dma", fmt , ## args)
+#define CX18_DEBUG_IOCTL(fmt, args...) CX18_DEBUG(CX18_DBGFLG_IOCTL, "ioctl", fmt , ## args)
+#define CX18_DEBUG_FILE(fmt, args...)  CX18_DEBUG(CX18_DBGFLG_FILE, "file", fmt , ## args)
+#define CX18_DEBUG_I2C(fmt, args...)   CX18_DEBUG(CX18_DBGFLG_I2C, "i2c", fmt , ## args)
+#define CX18_DEBUG_IRQ(fmt, args...)   CX18_DEBUG(CX18_DBGFLG_IRQ, "irq", fmt , ## args)
+
+#define CX18_DEBUG_HIGH_VOL(x, type, fmt, args...) \
+       do { \
+               if (((x) & cx18_debug) && (cx18_debug & CX18_DBGFLG_HIGHVOL)) \
+                       printk(KERN_INFO "cx18%d " type ": " fmt, cx->num , ## args); \
+       } while (0)
+#define CX18_DEBUG_HI_WARN(fmt, args...)  CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_WARN, "warning", fmt , ## args)
+#define CX18_DEBUG_HI_INFO(fmt, args...)  CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_INFO, "info", fmt , ## args)
+#define CX18_DEBUG_HI_API(fmt, args...)   CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_API, "api", fmt , ## args)
+#define CX18_DEBUG_HI_DMA(fmt, args...)   CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_DMA, "dma", fmt , ## args)
+#define CX18_DEBUG_HI_IOCTL(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_IOCTL, "ioctl", fmt , ## args)
+#define CX18_DEBUG_HI_FILE(fmt, args...)  CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_FILE, "file", fmt , ## args)
+#define CX18_DEBUG_HI_I2C(fmt, args...)   CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_I2C, "i2c", fmt , ## args)
+#define CX18_DEBUG_HI_IRQ(fmt, args...)   CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_IRQ, "irq", fmt , ## args)
+
+/* Standard kernel messages */
+#define CX18_ERR(fmt, args...)      printk(KERN_ERR  "cx18-%d: " fmt, cx->num , ## args)
+#define CX18_WARN(fmt, args...)     printk(KERN_WARNING "cx18-%d: " fmt, cx->num , ## args)
+#define CX18_INFO(fmt, args...)     printk(KERN_INFO "cx18-%d: " fmt, cx->num , ## args)
+
+/* Values for CX18_API_DEC_PLAYBACK_SPEED mpeg_frame_type_mask parameter: */
+#define MPEG_FRAME_TYPE_IFRAME 1
+#define MPEG_FRAME_TYPE_IFRAME_PFRAME 3
+#define MPEG_FRAME_TYPE_ALL 7
+
+#define CX18_MAX_PGM_INDEX (400)
+
+extern int cx18_debug;
+
+
+struct cx18_options {
+       int megabytes[CX18_MAX_STREAMS]; /* Size in megabytes of each stream */
+       int cardtype;           /* force card type on load */
+       int tuner;              /* set tuner on load */
+       int radio;              /* enable/disable radio */
+};
+
+/* per-buffer bit flags */
+#define CX18_F_B_NEED_BUF_SWAP  0      /* this buffer should be byte swapped */
+
+/* per-stream, s_flags */
+#define CX18_F_S_CLAIMED       3       /* this stream is claimed */
+#define CX18_F_S_STREAMING      4      /* the fw is decoding/encoding this stream */
+#define CX18_F_S_INTERNAL_USE  5       /* this stream is used internally (sliced VBI processing) */
+#define CX18_F_S_STREAMOFF     7       /* signal end of stream EOS */
+#define CX18_F_S_APPL_IO        8      /* this stream is used read/written by an application */
+
+/* per-cx18, i_flags */
+#define CX18_F_I_LOADED_FW     0       /* Loaded the firmware the first time */
+#define CX18_F_I_EOS           4       /* End of encoder stream reached */
+#define CX18_F_I_RADIO_USER    5       /* The radio tuner is selected */
+#define CX18_F_I_ENC_PAUSED    13      /* the encoder is paused */
+#define CX18_F_I_INITED                21      /* set after first open */
+#define CX18_F_I_FAILED                22      /* set if first open failed */
+
+/* These are the VBI types as they appear in the embedded VBI private packets. */
+#define CX18_SLICED_TYPE_TELETEXT_B     (1)
+#define CX18_SLICED_TYPE_CAPTION_525    (4)
+#define CX18_SLICED_TYPE_WSS_625        (5)
+#define CX18_SLICED_TYPE_VPS            (7)
+
+struct cx18_buffer {
+       struct list_head list;
+       dma_addr_t dma_handle;
+       u32 id;
+       unsigned long b_flags;
+       char *buf;
+
+       u32 bytesused;
+       u32 readpos;
+};
+
+struct cx18_queue {
+       struct list_head list;
+       u32 buffers;
+       u32 length;
+       u32 bytesused;
+};
+
+struct cx18_dvb {
+       struct dmx_frontend hw_frontend;
+       struct dmx_frontend mem_frontend;
+       struct dmxdev dmxdev;
+       struct dvb_adapter dvb_adapter;
+       struct dvb_demux demux;
+       struct dvb_frontend *fe;
+       struct dvb_net dvbnet;
+       int enabled;
+       int feeding;
+
+       struct mutex feedlock;
+
+};
+
+struct cx18;    /* forward reference */
+struct cx18_scb; /* forward reference */
+
+struct cx18_stream {
+       /* These first four fields are always set, even if the stream
+          is not actually created. */
+       struct video_device *v4l2dev;   /* NULL when stream not created */
+       struct cx18 *cx;                /* for ease of use */
+       const char *name;               /* name of the stream */
+       int type;                       /* stream type */
+       u32 handle;                     /* task handle */
+       unsigned mdl_offset;
+
+       u32 id;
+       spinlock_t qlock;       /* locks access to the queues */
+       unsigned long s_flags;  /* status flags, see above */
+       int dma;                /* can be PCI_DMA_TODEVICE,
+                                  PCI_DMA_FROMDEVICE or
+                                  PCI_DMA_NONE */
+       u64 dma_pts;
+       wait_queue_head_t waitq;
+
+       /* Buffer Stats */
+       u32 buffers;
+       u32 buf_size;
+       u32 buffers_stolen;
+
+       /* Buffer Queues */
+       struct cx18_queue q_free;       /* free buffers */
+       struct cx18_queue q_full;       /* full buffers */
+       struct cx18_queue q_io;         /* waiting for I/O */
+
+       /* DVB / Digital Transport */
+       struct cx18_dvb dvb;
+};
+
+struct cx18_open_id {
+       u32 open_id;
+       int type;
+       enum v4l2_priority prio;
+       struct cx18 *cx;
+};
+
+/* forward declaration of struct defined in cx18-cards.h */
+struct cx18_card;
+
+
+#define CX18_VBI_FRAMES 32
+
+/* VBI data */
+struct vbi_info {
+       u32 enc_size;
+       u32 frame;
+       u8 cc_data_odd[256];
+       u8 cc_data_even[256];
+       int cc_pos;
+       u8 cc_no_update;
+       u8 vps[5];
+       u8 vps_found;
+       int wss;
+       u8 wss_found;
+       u8 wss_no_update;
+       u32 raw_decoder_line_size;
+       u8 raw_decoder_sav_odd_field;
+       u8 raw_decoder_sav_even_field;
+       u32 sliced_decoder_line_size;
+       u8 sliced_decoder_sav_odd_field;
+       u8 sliced_decoder_sav_even_field;
+       struct v4l2_format in;
+       /* convenience pointer to sliced struct in vbi_in union */
+       struct v4l2_sliced_vbi_format *sliced_in;
+       u32 service_set_in;
+       int insert_mpeg;
+
+       /* Buffer for the maximum of 2 * 18 * packet_size sliced VBI lines.
+          One for /dev/vbi0 and one for /dev/vbi8 */
+       struct v4l2_sliced_vbi_data sliced_data[36];
+
+       /* Buffer for VBI data inserted into MPEG stream.
+          The first byte is a dummy byte that's never used.
+          The next 16 bytes contain the MPEG header for the VBI data,
+          the remainder is the actual VBI data.
+          The max size accepted by the MPEG VBI reinsertion turns out
+          to be 1552 bytes, which happens to be 4 + (1 + 42) * (2 * 18) bytes,
+          where 4 is a four byte header, 42 is the max sliced VBI payload, 1 is
+          a single line header byte and 2 * 18 is the number of VBI lines per frame.
+
+          However, it seems that the data must be 1K aligned, so we have to
+          pad the data until the 1 or 2 K boundary.
+
+          This pointer array will allocate 2049 bytes to store each VBI frame. */
+       u8 *sliced_mpeg_data[CX18_VBI_FRAMES];
+       u32 sliced_mpeg_size[CX18_VBI_FRAMES];
+       struct cx18_buffer sliced_mpeg_buf;
+       u32 inserted_frame;
+
+       u32 start[2], count;
+       u32 raw_size;
+       u32 sliced_size;
+};
+
+/* Per cx23418, per I2C bus private algo callback data */
+struct cx18_i2c_algo_callback_data {
+       struct cx18 *cx;
+       int bus_index;   /* 0 or 1 for the cx23418's 1st or 2nd I2C bus */
+};
+
+/* Struct to hold info about cx18 cards */
+struct cx18 {
+       int num;                /* board number, -1 during init! */
+       char name[8];           /* board name for printk and interrupts (e.g. 'cx180') */
+       struct pci_dev *dev;    /* PCI device */
+       const struct cx18_card *card;   /* card information */
+       const char *card_name;  /* full name of the card */
+       const struct cx18_card_tuner_i2c *card_i2c; /* i2c addresses to probe for tuner */
+       u8 is_50hz;
+       u8 is_60hz;
+       u8 is_out_50hz;
+       u8 is_out_60hz;
+       u8 nof_inputs;          /* number of video inputs */
+       u8 nof_audio_inputs;    /* number of audio inputs */
+       u16 buffer_id;          /* buffer ID counter */
+       u32 v4l2_cap;           /* V4L2 capabilities of card */
+       u32 hw_flags;           /* Hardware description of the board */
+       unsigned mdl_offset;
+       struct cx18_scb *scb;   /* pointer to SCB */
+
+       struct cx18_av_state av_state;
+
+       /* codec settings */
+       struct cx2341x_mpeg_params params;
+       u32 filter_mode;
+       u32 temporal_strength;
+       u32 spatial_strength;
+
+       /* dualwatch */
+       unsigned long dualwatch_jiffies;
+       u16 dualwatch_stereo_mode;
+
+       /* Digitizer type */
+       int digitizer;          /* 0x00EF = saa7114 0x00FO = saa7115 0x0106 = mic */
+
+       struct mutex serialize_lock;    /* mutex used to serialize open/close/start/stop/ioctl operations */
+       struct cx18_options options;    /* User options */
+       int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */
+       struct cx18_stream streams[CX18_MAX_STREAMS];   /* Stream data */
+       unsigned long i_flags;  /* global cx18 flags */
+       atomic_t capturing;     /* count number of active capture streams */
+       spinlock_t lock;        /* lock access to this struct */
+       int search_pack_header;
+
+       spinlock_t dma_reg_lock; /* lock access to DMA engine registers */
+
+       int open_id;            /* incremented each time an open occurs, used as
+                                  unique ID. Starts at 1, so 0 can be used as
+                                  uninitialized value in the stream->id. */
+
+       u32 base_addr;
+       struct v4l2_prio_state prio;
+
+       u8 card_rev;
+       void __iomem *enc_mem, *reg_mem;
+
+       struct vbi_info vbi;
+
+       u32 pgm_info_offset;
+       u32 pgm_info_num;
+       u32 pgm_info_write_idx;
+       u32 pgm_info_read_idx;
+       struct v4l2_enc_idx_entry pgm_info[CX18_MAX_PGM_INDEX];
+
+       u64 mpg_data_received;
+       u64 vbi_data_inserted;
+
+       wait_queue_head_t mb_apu_waitq;
+       wait_queue_head_t mb_cpu_waitq;
+       wait_queue_head_t mb_epu_waitq;
+       wait_queue_head_t mb_hpu_waitq;
+       wait_queue_head_t cap_w;
+       /* when the current DMA is finished this queue is woken up */
+       wait_queue_head_t dma_waitq;
+
+       /* i2c */
+       struct i2c_adapter i2c_adap[2];
+       struct i2c_algo_bit_data i2c_algo[2];
+       struct cx18_i2c_algo_callback_data i2c_algo_cb_data[2];
+       struct i2c_client i2c_client[2];
+       struct mutex i2c_bus_lock[2];
+       struct i2c_client *i2c_clients[I2C_CLIENTS_MAX];
+
+       /* v4l2 and User settings */
+
+       /* codec settings */
+       u32 audio_input;
+       u32 active_input;
+       u32 active_output;
+       v4l2_std_id std;
+       v4l2_std_id tuner_std;  /* The norm of the tuner (fixed) */
+};
+
+/* Globals */
+extern struct cx18 *cx18_cards[];
+extern int cx18_cards_active;
+extern int cx18_first_minor;
+extern spinlock_t cx18_cards_lock;
+
+/*==============Prototypes==================*/
+
+/* Return non-zero if a signal is pending */
+int cx18_msleep_timeout(unsigned int msecs, int intr);
+
+/* Wait on queue, returns -EINTR if interrupted */
+int cx18_waitq(wait_queue_head_t *waitq);
+
+/* Read Hauppauge eeprom */
+struct tveeprom; /* forward reference */
+void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv);
+
+/* First-open initialization: load firmware, etc. */
+int cx18_init_on_first_open(struct cx18 *cx);
+
+/* This is a PCI post thing, where if the pci register is not read, then
+   the write doesn't always take effect right away. By reading back the
+   register any pending PCI writes will be performed (in order), and so
+   you can be sure that the writes are guaranteed to be done.
+
+   Rarely needed, only in some timing sensitive cases.
+   Apparently if this is not done some motherboards seem
+   to kill the firmware and get into the broken state until computer is
+   rebooted. */
+#define write_sync(val, reg) \
+       do { writel(val, reg); readl(reg); } while (0)
+
+#define read_reg(reg) readl(cx->reg_mem + (reg))
+#define write_reg(val, reg) writel(val, cx->reg_mem + (reg))
+#define write_reg_sync(val, reg) \
+       do { write_reg(val, reg); read_reg(reg); } while (0)
+
+#define read_enc(addr) readl(cx->enc_mem + (u32)(addr))
+#define write_enc(val, addr) writel(val, cx->enc_mem + (u32)(addr))
+#define write_enc_sync(val, addr) \
+       do { write_enc(val, addr); read_enc(addr); } while (0)
+
+#define sw1_irq_enable(val) do { \
+       write_reg(val, SW1_INT_STATUS); \
+       write_reg(read_reg(SW1_INT_ENABLE_PCI) | (val), SW1_INT_ENABLE_PCI); \
+} while (0)
+
+#define sw1_irq_disable(val) \
+       write_reg(read_reg(SW1_INT_ENABLE_PCI) & ~(val), SW1_INT_ENABLE_PCI);
+
+#define sw2_irq_enable(val) do { \
+       write_reg(val, SW2_INT_STATUS); \
+       write_reg(read_reg(SW2_INT_ENABLE_PCI) | (val), SW2_INT_ENABLE_PCI); \
+} while (0)
+
+#define sw2_irq_disable(val) \
+       write_reg(read_reg(SW2_INT_ENABLE_PCI) & ~(val), SW2_INT_ENABLE_PCI);
+
+#define setup_page(addr) do { \
+    u32 val = read_reg(0xD000F8) & ~0x1f00; \
+    write_reg(val | (((addr) >> 17) & 0x1f00), 0xD000F8); \
+} while (0)
+
+#endif /* CX18_DRIVER_H */
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c
new file mode 100644 (file)
index 0000000..65efe69
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ *  cx18 functions for DVB support
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "cx18-version.h"
+#include "cx18-dvb.h"
+#include "cx18-streams.h"
+#include "cx18-cards.h"
+#include "s5h1409.h"
+
+/* Wait until the MXL500X driver is merged */
+#ifdef HAVE_MXL500X
+#include "mxl500x.h"
+#endif
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define CX18_REG_DMUX_NUM_PORT_0_CONTROL 0xd5a000
+
+#ifdef HAVE_MXL500X
+static struct mxl500x_config hauppauge_hvr1600_tuner = {
+       .delsys    = MXL500x_MODE_ATSC,
+       .octf      = MXL500x_OCTF_CH,
+       .xtal_freq = 16000000,
+       .iflo_freq = 5380000,
+       .ref_freq  = 322800000,
+       .rssi_ena  = MXL_RSSI_ENABLE,
+       .addr      = 0xC6 >> 1,
+};
+
+static struct s5h1409_config hauppauge_hvr1600_config = {
+       .demod_address = 0x32 >> 1,
+       .output_mode   = S5H1409_SERIAL_OUTPUT,
+       .gpio          = S5H1409_GPIO_ON,
+       .qam_if        = 44000,
+       .inversion     = S5H1409_INVERSION_OFF,
+       .status_mode   = S5H1409_DEMODLOCKING,
+       .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
+
+};
+#endif
+
+static int dvb_register(struct cx18_stream *stream);
+
+/* Kernel DVB framework calls this when the feed needs to start.
+ * The CX18 framework should enable the transport DMA handling
+ * and queue processing.
+ */
+static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux = feed->demux;
+       struct cx18_stream *stream = (struct cx18_stream *) demux->priv;
+       struct cx18 *cx = stream->cx;
+       int ret = -EINVAL;
+       u32 v;
+
+       CX18_DEBUG_INFO("Start feed: pid = 0x%x index = %d\n",
+                       feed->pid, feed->index);
+       switch (cx->card->type) {
+       case CX18_CARD_HVR_1600_ESMT:
+       case CX18_CARD_HVR_1600_SAMSUNG:
+               v = read_reg(CX18_REG_DMUX_NUM_PORT_0_CONTROL);
+               v |= 0x00400000; /* Serial Mode */
+               v |= 0x00002000; /* Data Length - Byte */
+               v |= 0x00010000; /* Error - Polarity */
+               v |= 0x00020000; /* Error - Passthru */
+               v |= 0x000c0000; /* Error - Ignore */
+               write_reg(v, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
+               break;
+
+       default:
+               /* Assumption - Parallel transport - Signalling
+                * undefined or default.
+                */
+               break;
+       }
+
+       if (!demux->dmx.frontend)
+               return -EINVAL;
+
+       if (stream) {
+               mutex_lock(&stream->dvb.feedlock);
+               if (stream->dvb.feeding++ == 0) {
+                       CX18_DEBUG_INFO("Starting Transport DMA\n");
+                       ret = cx18_start_v4l2_encode_stream(stream);
+               } else
+                       ret = 0;
+               mutex_unlock(&stream->dvb.feedlock);
+       }
+
+       return ret;
+}
+
+/* Kernel DVB framework calls this when the feed needs to stop. */
+static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux = feed->demux;
+       struct cx18_stream *stream = (struct cx18_stream *)demux->priv;
+       struct cx18 *cx = stream->cx;
+       int ret = -EINVAL;
+
+       CX18_DEBUG_INFO("Stop feed: pid = 0x%x index = %d\n",
+                       feed->pid, feed->index);
+
+       if (stream) {
+               mutex_lock(&stream->dvb.feedlock);
+               if (--stream->dvb.feeding == 0) {
+                       CX18_DEBUG_INFO("Stopping Transport DMA\n");
+                       ret = cx18_stop_v4l2_encode_stream(stream, 0);
+               } else
+                       ret = 0;
+               mutex_unlock(&stream->dvb.feedlock);
+       }
+
+       return ret;
+}
+
+int cx18_dvb_register(struct cx18_stream *stream)
+{
+       struct cx18 *cx = stream->cx;
+       struct cx18_dvb *dvb = &stream->dvb;
+       struct dvb_adapter *dvb_adapter;
+       struct dvb_demux *dvbdemux;
+       struct dmx_demux *dmx;
+       int ret;
+
+       if (!dvb)
+               return -EINVAL;
+
+       ret = dvb_register_adapter(&dvb->dvb_adapter,
+                       CX18_DRIVER_NAME,
+                       THIS_MODULE, &cx->dev->dev, adapter_nr);
+       if (ret < 0)
+               goto err_out;
+
+       dvb_adapter = &dvb->dvb_adapter;
+
+       dvbdemux = &dvb->demux;
+
+       dvbdemux->priv = (void *)stream;
+
+       dvbdemux->filternum = 256;
+       dvbdemux->feednum = 256;
+       dvbdemux->start_feed = cx18_dvb_start_feed;
+       dvbdemux->stop_feed = cx18_dvb_stop_feed;
+       dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
+               DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
+       ret = dvb_dmx_init(dvbdemux);
+       if (ret < 0)
+               goto err_dvb_unregister_adapter;
+
+       dmx = &dvbdemux->dmx;
+
+       dvb->hw_frontend.source = DMX_FRONTEND_0;
+       dvb->mem_frontend.source = DMX_MEMORY_FE;
+       dvb->dmxdev.filternum = 256;
+       dvb->dmxdev.demux = dmx;
+
+       ret = dvb_dmxdev_init(&dvb->dmxdev, dvb_adapter);
+       if (ret < 0)
+               goto err_dvb_dmx_release;
+
+       ret = dmx->add_frontend(dmx, &dvb->hw_frontend);
+       if (ret < 0)
+               goto err_dvb_dmxdev_release;
+
+       ret = dmx->add_frontend(dmx, &dvb->mem_frontend);
+       if (ret < 0)
+               goto err_remove_hw_frontend;
+
+       ret = dmx->connect_frontend(dmx, &dvb->hw_frontend);
+       if (ret < 0)
+               goto err_remove_mem_frontend;
+
+       ret = dvb_register(stream);
+       if (ret < 0)
+               goto err_disconnect_frontend;
+
+       dvb_net_init(dvb_adapter, &dvb->dvbnet, dmx);
+
+       CX18_INFO("DVB Frontend registered\n");
+       mutex_init(&dvb->feedlock);
+       dvb->enabled = 1;
+       return ret;
+
+err_disconnect_frontend:
+       dmx->disconnect_frontend(dmx);
+err_remove_mem_frontend:
+       dmx->remove_frontend(dmx, &dvb->mem_frontend);
+err_remove_hw_frontend:
+       dmx->remove_frontend(dmx, &dvb->hw_frontend);
+err_dvb_dmxdev_release:
+       dvb_dmxdev_release(&dvb->dmxdev);
+err_dvb_dmx_release:
+       dvb_dmx_release(dvbdemux);
+err_dvb_unregister_adapter:
+       dvb_unregister_adapter(dvb_adapter);
+err_out:
+       return ret;
+}
+
+void cx18_dvb_unregister(struct cx18_stream *stream)
+{
+       struct cx18 *cx = stream->cx;
+       struct cx18_dvb *dvb = &stream->dvb;
+       struct dvb_adapter *dvb_adapter;
+       struct dvb_demux *dvbdemux;
+       struct dmx_demux *dmx;
+
+       CX18_INFO("unregister DVB\n");
+
+       dvb_adapter = &dvb->dvb_adapter;
+       dvbdemux = &dvb->demux;
+       dmx = &dvbdemux->dmx;
+
+       dmx->close(dmx);
+       dvb_net_release(&dvb->dvbnet);
+       dmx->remove_frontend(dmx, &dvb->mem_frontend);
+       dmx->remove_frontend(dmx, &dvb->hw_frontend);
+       dvb_dmxdev_release(&dvb->dmxdev);
+       dvb_dmx_release(dvbdemux);
+       dvb_unregister_frontend(dvb->fe);
+       dvb_frontend_detach(dvb->fe);
+       dvb_unregister_adapter(dvb_adapter);
+}
+
+/* All the DVB attach calls go here, this function get's modified
+ * for each new card. No other function in this file needs
+ * to change.
+ */
+static int dvb_register(struct cx18_stream *stream)
+{
+       struct cx18_dvb *dvb = &stream->dvb;
+       struct cx18 *cx = stream->cx;
+       int ret = 0;
+
+       switch (cx->card->type) {
+/* Wait until the MXL500X driver is merged */
+#ifdef HAVE_MXL500X
+       case CX18_CARD_HVR_1600_ESMT:
+       case CX18_CARD_HVR_1600_SAMSUNG:
+               dvb->fe = dvb_attach(s5h1409_attach,
+                       &hauppauge_hvr1600_config,
+                       &cx->i2c_adap[0]);
+               if (dvb->fe != NULL) {
+                       dvb_attach(mxl500x_attach, dvb->fe,
+                               &hauppauge_hvr1600_tuner,
+                               &cx->i2c_adap[0]);
+                       ret = 0;
+               }
+               break;
+#endif
+       default:
+               /* No Digital Tv Support */
+               break;
+       }
+
+       if (dvb->fe == NULL) {
+               CX18_ERR("frontend initialization failed\n");
+               return -1;
+       }
+
+       ret = dvb_register_frontend(&dvb->dvb_adapter, dvb->fe);
+       if (ret < 0) {
+               if (dvb->fe->ops.release)
+                       dvb->fe->ops.release(dvb->fe);
+               return ret;
+       }
+
+       return ret;
+}
diff --git a/drivers/media/video/cx18/cx18-dvb.h b/drivers/media/video/cx18/cx18-dvb.h
new file mode 100644 (file)
index 0000000..d6a6ccd
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  cx18 functions for DVB support
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@hauppauge.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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "cx18-driver.h"
+
+int cx18_dvb_register(struct cx18_stream *stream);
+void cx18_dvb_unregister(struct cx18_stream *stream);
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
new file mode 100644 (file)
index 0000000..6930306
--- /dev/null
@@ -0,0 +1,711 @@
+/*
+ *  cx18 file operation functions
+ *
+ *  Derived from ivtv-fileops.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 "cx18-driver.h"
+#include "cx18-fileops.h"
+#include "cx18-i2c.h"
+#include "cx18-queue.h"
+#include "cx18-vbi.h"
+#include "cx18-audio.h"
+#include "cx18-mailbox.h"
+#include "cx18-scb.h"
+#include "cx18-streams.h"
+#include "cx18-controls.h"
+#include "cx18-ioctl.h"
+#include "cx18-cards.h"
+
+/* This function tries to claim the stream for a specific file descriptor.
+   If no one else is using this stream then the stream is claimed and
+   associated VBI streams are also automatically claimed.
+   Possible error returns: -EBUSY if someone else has claimed
+   the stream or 0 on success. */
+int cx18_claim_stream(struct cx18_open_id *id, int type)
+{
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[type];
+       struct cx18_stream *s_vbi;
+       int vbi_type;
+
+       if (test_and_set_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
+               /* someone already claimed this stream */
+               if (s->id == id->open_id) {
+                       /* yes, this file descriptor did. So that's OK. */
+                       return 0;
+               }
+               if (s->id == -1 && type == CX18_ENC_STREAM_TYPE_VBI) {
+                       /* VBI is handled already internally, now also assign
+                          the file descriptor to this stream for external
+                          reading of the stream. */
+                       s->id = id->open_id;
+                       CX18_DEBUG_INFO("Start Read VBI\n");
+                       return 0;
+               }
+               /* someone else is using this stream already */
+               CX18_DEBUG_INFO("Stream %d is busy\n", type);
+               return -EBUSY;
+       }
+       s->id = id->open_id;
+
+       /* CX18_DEC_STREAM_TYPE_MPG needs to claim CX18_DEC_STREAM_TYPE_VBI,
+          CX18_ENC_STREAM_TYPE_MPG needs to claim CX18_ENC_STREAM_TYPE_VBI
+          (provided VBI insertion is on and sliced VBI is selected), for all
+          other streams we're done */
+       if (type == CX18_ENC_STREAM_TYPE_MPG &&
+                  cx->vbi.insert_mpeg && cx->vbi.sliced_in->service_set) {
+               vbi_type = CX18_ENC_STREAM_TYPE_VBI;
+       } else {
+               return 0;
+       }
+       s_vbi = &cx->streams[vbi_type];
+
+       set_bit(CX18_F_S_CLAIMED, &s_vbi->s_flags);
+
+       /* mark that it is used internally */
+       set_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags);
+       return 0;
+}
+
+/* This function releases a previously claimed stream. It will take into
+   account associated VBI streams. */
+void cx18_release_stream(struct cx18_stream *s)
+{
+       struct cx18 *cx = s->cx;
+       struct cx18_stream *s_vbi;
+
+       s->id = -1;
+       if (s->type == CX18_ENC_STREAM_TYPE_VBI &&
+               test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) {
+               /* this stream is still in use internally */
+               return;
+       }
+       if (!test_and_clear_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
+               CX18_DEBUG_WARN("Release stream %s not in use!\n", s->name);
+               return;
+       }
+
+       cx18_flush_queues(s);
+
+       /* CX18_ENC_STREAM_TYPE_MPG needs to release CX18_ENC_STREAM_TYPE_VBI,
+          for all other streams we're done */
+       if (s->type == CX18_ENC_STREAM_TYPE_MPG)
+               s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+       else
+               return;
+
+       /* clear internal use flag */
+       if (!test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags)) {
+               /* was already cleared */
+               return;
+       }
+       if (s_vbi->id != -1) {
+               /* VBI stream still claimed by a file descriptor */
+               return;
+       }
+       clear_bit(CX18_F_S_CLAIMED, &s_vbi->s_flags);
+       cx18_flush_queues(s_vbi);
+}
+
+static void cx18_dualwatch(struct cx18 *cx)
+{
+       struct v4l2_tuner vt;
+       u16 new_bitmap;
+       u16 new_stereo_mode;
+       const u16 stereo_mask = 0x0300;
+       const u16 dual = 0x0200;
+
+       new_stereo_mode = cx->params.audio_properties & stereo_mask;
+       memset(&vt, 0, sizeof(vt));
+       cx18_call_i2c_clients(cx, VIDIOC_G_TUNER, &vt);
+       if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 &&
+                       (vt.rxsubchans & V4L2_TUNER_SUB_LANG2))
+               new_stereo_mode = dual;
+
+       if (new_stereo_mode == cx->dualwatch_stereo_mode)
+               return;
+
+       new_bitmap = new_stereo_mode | (cx->params.audio_properties & ~stereo_mask);
+
+       CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. new audio_bitmask=0x%ux\n",
+                          cx->dualwatch_stereo_mode, new_stereo_mode, new_bitmap);
+
+       if (cx18_vapi(cx, CX18_CPU_SET_AUDIO_PARAMETERS, 2,
+                               cx18_find_handle(cx), new_bitmap) == 0) {
+               cx->dualwatch_stereo_mode = new_stereo_mode;
+               return;
+       }
+       CX18_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
+}
+
+
+static struct cx18_buffer *cx18_get_buffer(struct cx18_stream *s, int non_block, int *err)
+{
+       struct cx18 *cx = s->cx;
+       struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+       struct cx18_buffer *buf;
+       DEFINE_WAIT(wait);
+
+       *err = 0;
+       while (1) {
+               if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
+
+                       if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) {
+                               cx->dualwatch_jiffies = jiffies;
+                               cx18_dualwatch(cx);
+                       }
+                       if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
+                           !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
+                               while ((buf = cx18_dequeue(s_vbi, &s_vbi->q_full))) {
+                                       /* byteswap and process VBI data */
+/*                                     cx18_process_vbi_data(cx, buf, s_vbi->dma_pts, s_vbi->type); */
+                                       cx18_enqueue(s_vbi, buf, &s_vbi->q_free);
+                               }
+                       }
+                       buf = &cx->vbi.sliced_mpeg_buf;
+                       if (buf->readpos != buf->bytesused)
+                               return buf;
+               }
+
+               /* do we have leftover data? */
+               buf = cx18_dequeue(s, &s->q_io);
+               if (buf)
+                       return buf;
+
+               /* do we have new data? */
+               buf = cx18_dequeue(s, &s->q_full);
+               if (buf) {
+                       if (!test_and_clear_bit(CX18_F_B_NEED_BUF_SWAP,
+                                               &buf->b_flags))
+                               return buf;
+                       if (s->type == CX18_ENC_STREAM_TYPE_MPG)
+                               /* byteswap MPG data */
+                               cx18_buf_swap(buf);
+                       else {
+                               /* byteswap and process VBI data */
+                               cx18_process_vbi_data(cx, buf,
+                                               s->dma_pts, s->type);
+                       }
+                       return buf;
+               }
+
+               /* return if end of stream */
+               if (!test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+                       CX18_DEBUG_INFO("EOS %s\n", s->name);
+                       return NULL;
+               }
+
+               /* return if file was opened with O_NONBLOCK */
+               if (non_block) {
+                       *err = -EAGAIN;
+                       return NULL;
+               }
+
+               /* wait for more data to arrive */
+               prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
+               /* New buffers might have become available before we were added
+                  to the waitqueue */
+               if (!s->q_full.buffers)
+                       schedule();
+               finish_wait(&s->waitq, &wait);
+               if (signal_pending(current)) {
+                       /* return if a signal was received */
+                       CX18_DEBUG_INFO("User stopped %s\n", s->name);
+                       *err = -EINTR;
+                       return NULL;
+               }
+       }
+}
+
+static void cx18_setup_sliced_vbi_buf(struct cx18 *cx)
+{
+       int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
+
+       cx->vbi.sliced_mpeg_buf.buf = cx->vbi.sliced_mpeg_data[idx];
+       cx->vbi.sliced_mpeg_buf.bytesused = cx->vbi.sliced_mpeg_size[idx];
+       cx->vbi.sliced_mpeg_buf.readpos = 0;
+}
+
+static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
+               struct cx18_buffer *buf, char __user *ubuf, size_t ucount)
+{
+       struct cx18 *cx = s->cx;
+       size_t len = buf->bytesused - buf->readpos;
+
+       if (len > ucount)
+               len = ucount;
+       if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG &&
+           cx->vbi.sliced_in->service_set && buf != &cx->vbi.sliced_mpeg_buf) {
+               const char *start = buf->buf + buf->readpos;
+               const char *p = start + 1;
+               const u8 *q;
+               u8 ch = cx->search_pack_header ? 0xba : 0xe0;
+               int stuffing, i;
+
+               while (start + len > p) {
+                       q = memchr(p, 0, start + len - p);
+                       if (q == NULL)
+                               break;
+                       p = q + 1;
+                       if ((char *)q + 15 >= buf->buf + buf->bytesused ||
+                           q[1] != 0 || q[2] != 1 || q[3] != ch)
+                               continue;
+                       if (!cx->search_pack_header) {
+                               if ((q[6] & 0xc0) != 0x80)
+                                       continue;
+                               if (((q[7] & 0xc0) == 0x80 &&
+                                    (q[9] & 0xf0) == 0x20) ||
+                                   ((q[7] & 0xc0) == 0xc0 &&
+                                    (q[9] & 0xf0) == 0x30)) {
+                                       ch = 0xba;
+                                       cx->search_pack_header = 1;
+                                       p = q + 9;
+                               }
+                               continue;
+                       }
+                       stuffing = q[13] & 7;
+                       /* all stuffing bytes must be 0xff */
+                       for (i = 0; i < stuffing; i++)
+                               if (q[14 + i] != 0xff)
+                                       break;
+                       if (i == stuffing &&
+                           (q[4] & 0xc4) == 0x44 &&
+                           (q[12] & 3) == 3 &&
+                           q[14 + stuffing] == 0 &&
+                           q[15 + stuffing] == 0 &&
+                           q[16 + stuffing] == 1) {
+                               cx->search_pack_header = 0;
+                               len = (char *)q - start;
+                               cx18_setup_sliced_vbi_buf(cx);
+                               break;
+                       }
+               }
+       }
+       if (copy_to_user(ubuf, (u8 *)buf->buf + buf->readpos, len)) {
+               CX18_DEBUG_WARN("copy %zd bytes to user failed for %s\n",
+                               len, s->name);
+               return -EFAULT;
+       }
+       buf->readpos += len;
+       if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
+           buf != &cx->vbi.sliced_mpeg_buf)
+               cx->mpg_data_received += len;
+       return len;
+}
+
+static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
+               size_t tot_count, int non_block)
+{
+       struct cx18 *cx = s->cx;
+       size_t tot_written = 0;
+       int single_frame = 0;
+
+       if (atomic_read(&cx->capturing) == 0 && s->id == -1) {
+               /* shouldn't happen */
+               CX18_DEBUG_WARN("Stream %s not initialized before read\n",
+                               s->name);
+               return -EIO;
+       }
+
+       /* Each VBI buffer is one frame, the v4l2 API says that for VBI the
+          frames should arrive one-by-one, so make sure we never output more
+          than one VBI frame at a time */
+       if (s->type == CX18_ENC_STREAM_TYPE_VBI &&
+           cx->vbi.sliced_in->service_set)
+               single_frame = 1;
+
+       for (;;) {
+               struct cx18_buffer *buf;
+               int rc;
+
+               buf = cx18_get_buffer(s, non_block, &rc);
+               /* if there is no data available... */
+               if (buf == NULL) {
+                       /* if we got data, then return that regardless */
+                       if (tot_written)
+                               break;
+                       /* EOS condition */
+                       if (rc == 0) {
+                               clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+                               clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
+                               cx18_release_stream(s);
+                       }
+                       /* set errno */
+                       return rc;
+               }
+
+               rc = cx18_copy_buf_to_user(s, buf, ubuf + tot_written,
+                               tot_count - tot_written);
+
+               if (buf != &cx->vbi.sliced_mpeg_buf) {
+                       if (buf->readpos == buf->bytesused) {
+                               cx18_buf_sync_for_device(s, buf);
+                               cx18_enqueue(s, buf, &s->q_free);
+                               cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5,
+                                       s->handle,
+                                       (void *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem,
+                                       1, buf->id, s->buf_size);
+                       } else
+                               cx18_enqueue(s, buf, &s->q_io);
+               } else if (buf->readpos == buf->bytesused) {
+                       int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
+
+                       cx->vbi.sliced_mpeg_size[idx] = 0;
+                       cx->vbi.inserted_frame++;
+                       cx->vbi_data_inserted += buf->bytesused;
+               }
+               if (rc < 0)
+                       return rc;
+               tot_written += rc;
+
+               if (tot_written == tot_count || single_frame)
+                       break;
+       }
+       return tot_written;
+}
+
+static ssize_t cx18_read_pos(struct cx18_stream *s, char __user *ubuf,
+               size_t count, loff_t *pos, int non_block)
+{
+       ssize_t rc = count ? cx18_read(s, ubuf, count, non_block) : 0;
+       struct cx18 *cx = s->cx;
+
+       CX18_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc);
+       if (rc > 0)
+               pos += rc;
+       return rc;
+}
+
+int cx18_start_capture(struct cx18_open_id *id)
+{
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[id->type];
+       struct cx18_stream *s_vbi;
+
+       if (s->type == CX18_ENC_STREAM_TYPE_RAD) {
+               /* you cannot read from these stream types. */
+               return -EPERM;
+       }
+
+       /* Try to claim this stream. */
+       if (cx18_claim_stream(id, s->type))
+               return -EBUSY;
+
+       /* If capture is already in progress, then we also have to
+          do nothing extra. */
+       if (test_bit(CX18_F_S_STREAMOFF, &s->s_flags) ||
+           test_and_set_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+               set_bit(CX18_F_S_APPL_IO, &s->s_flags);
+               return 0;
+       }
+
+       /* Start VBI capture if required */
+       s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+       if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
+           test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
+           !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
+               /* Note: the CX18_ENC_STREAM_TYPE_VBI is claimed
+                  automatically when the MPG stream is claimed.
+                  We only need to start the VBI capturing. */
+               if (cx18_start_v4l2_encode_stream(s_vbi)) {
+                       CX18_DEBUG_WARN("VBI capture start failed\n");
+
+                       /* Failure, clean up and return an error */
+                       clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
+                       clear_bit(CX18_F_S_STREAMING, &s->s_flags);
+                       /* also releases the associated VBI stream */
+                       cx18_release_stream(s);
+                       return -EIO;
+               }
+               CX18_DEBUG_INFO("VBI insertion started\n");
+       }
+
+       /* Tell the card to start capturing */
+       if (!cx18_start_v4l2_encode_stream(s)) {
+               /* We're done */
+               set_bit(CX18_F_S_APPL_IO, &s->s_flags);
+               /* Resume a possibly paused encoder */
+               if (test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
+                       cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, s->handle);
+               return 0;
+       }
+
+       /* failure, clean up */
+       CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name);
+
+       /* Note: the CX18_ENC_STREAM_TYPE_VBI is released
+          automatically when the MPG stream is released.
+          We only need to stop the VBI capturing. */
+       if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
+           test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
+               cx18_stop_v4l2_encode_stream(s_vbi, 0);
+               clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
+       }
+       clear_bit(CX18_F_S_STREAMING, &s->s_flags);
+       cx18_release_stream(s);
+       return -EIO;
+}
+
+ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
+               loff_t *pos)
+{
+       struct cx18_open_id *id = filp->private_data;
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[id->type];
+       int rc;
+
+       CX18_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
+
+       mutex_lock(&cx->serialize_lock);
+       rc = cx18_start_capture(id);
+       mutex_unlock(&cx->serialize_lock);
+       if (rc)
+               return rc;
+       return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
+}
+
+unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
+{
+       struct cx18_open_id *id = filp->private_data;
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[id->type];
+       int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+
+       /* Start a capture if there is none */
+       if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+               int rc;
+
+               mutex_lock(&cx->serialize_lock);
+               rc = cx18_start_capture(id);
+               mutex_unlock(&cx->serialize_lock);
+               if (rc) {
+                       CX18_DEBUG_INFO("Could not start capture for %s (%d)\n",
+                                       s->name, rc);
+                       return POLLERR;
+               }
+               CX18_DEBUG_FILE("Encoder poll started capture\n");
+       }
+
+       /* add stream's waitq to the poll list */
+       CX18_DEBUG_HI_FILE("Encoder poll\n");
+       poll_wait(filp, &s->waitq, wait);
+
+       if (s->q_full.length || s->q_io.length)
+               return POLLIN | POLLRDNORM;
+       if (eof)
+               return POLLHUP;
+       return 0;
+}
+
+void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
+{
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[id->type];
+
+       CX18_DEBUG_IOCTL("close() of %s\n", s->name);
+
+       /* 'Unclaim' this stream */
+
+       /* Stop capturing */
+       if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+               struct cx18_stream *s_vbi =
+                       &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+
+               CX18_DEBUG_INFO("close stopping capture\n");
+               /* Special case: a running VBI capture for VBI insertion
+                  in the mpeg stream. Need to stop that too. */
+               if (id->type == CX18_ENC_STREAM_TYPE_MPG &&
+                   test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
+                   !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
+                       CX18_DEBUG_INFO("close stopping embedded VBI capture\n");
+                       cx18_stop_v4l2_encode_stream(s_vbi, 0);
+               }
+               if (id->type == CX18_ENC_STREAM_TYPE_VBI &&
+                   test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags))
+                       /* Also used internally, don't stop capturing */
+                       s->id = -1;
+               else
+                       cx18_stop_v4l2_encode_stream(s, gop_end);
+       }
+       if (!gop_end) {
+               clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
+               clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+               cx18_release_stream(s);
+       }
+}
+
+int cx18_v4l2_close(struct inode *inode, struct file *filp)
+{
+       struct cx18_open_id *id = filp->private_data;
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[id->type];
+
+       CX18_DEBUG_IOCTL("close() of %s\n", s->name);
+
+       v4l2_prio_close(&cx->prio, &id->prio);
+
+       /* Easy case first: this stream was never claimed by us */
+       if (s->id != id->open_id) {
+               kfree(id);
+               return 0;
+       }
+
+       /* 'Unclaim' this stream */
+
+       /* Stop radio */
+       mutex_lock(&cx->serialize_lock);
+       if (id->type == CX18_ENC_STREAM_TYPE_RAD) {
+               /* Closing radio device, return to TV mode */
+               cx18_mute(cx);
+               /* Mark that the radio is no longer in use */
+               clear_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
+               /* Switch tuner to TV */
+               cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std);
+               /* Select correct audio input (i.e. TV tuner or Line in) */
+               cx18_audio_set_io(cx);
+               if (atomic_read(&cx->capturing) > 0) {
+                       /* Undo video mute */
+                       cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
+                               cx->params.video_mute |
+                                       (cx->params.video_mute_yuv << 8));
+               }
+               /* Done! Unmute and continue. */
+               cx18_unmute(cx);
+               cx18_release_stream(s);
+       } else {
+               cx18_stop_capture(id, 0);
+       }
+       kfree(id);
+       mutex_unlock(&cx->serialize_lock);
+       return 0;
+}
+
+static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
+{
+       struct cx18 *cx = s->cx;
+       struct cx18_open_id *item;
+
+       CX18_DEBUG_FILE("open %s\n", s->name);
+
+       /* Allocate memory */
+       item = kmalloc(sizeof(struct cx18_open_id), GFP_KERNEL);
+       if (NULL == item) {
+               CX18_DEBUG_WARN("nomem on v4l2 open\n");
+               return -ENOMEM;
+       }
+       item->cx = cx;
+       item->type = s->type;
+       v4l2_prio_open(&cx->prio, &item->prio);
+
+       item->open_id = cx->open_id++;
+       filp->private_data = item;
+
+       if (item->type == CX18_ENC_STREAM_TYPE_RAD) {
+               /* Try to claim this stream */
+               if (cx18_claim_stream(item, item->type)) {
+                       /* No, it's already in use */
+                       kfree(item);
+                       return -EBUSY;
+               }
+
+               if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
+                       if (atomic_read(&cx->capturing) > 0) {
+                               /* switching to radio while capture is
+                                  in progress is not polite */
+                               cx18_release_stream(s);
+                               kfree(item);
+                               return -EBUSY;
+                       }
+               }
+
+               /* Mark that the radio is being used. */
+               set_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
+               /* We have the radio */
+               cx18_mute(cx);
+               /* Switch tuner to radio */
+               cx18_call_i2c_clients(cx, AUDC_SET_RADIO, NULL);
+               /* Select the correct audio input (i.e. radio tuner) */
+               cx18_audio_set_io(cx);
+               /* Done! Unmute and continue. */
+               cx18_unmute(cx);
+       }
+       return 0;
+}
+
+int cx18_v4l2_open(struct inode *inode, struct file *filp)
+{
+       int res, x, y = 0;
+       struct cx18 *cx = NULL;
+       struct cx18_stream *s = NULL;
+       int minor = iminor(inode);
+
+       /* Find which card this open was on */
+       spin_lock(&cx18_cards_lock);
+       for (x = 0; cx == NULL && x < cx18_cards_active; x++) {
+               /* find out which stream this open was on */
+               for (y = 0; y < CX18_MAX_STREAMS; y++) {
+                       s = &cx18_cards[x]->streams[y];
+                       if (s->v4l2dev && s->v4l2dev->minor == minor) {
+                               cx = cx18_cards[x];
+                               break;
+                       }
+               }
+       }
+       spin_unlock(&cx18_cards_lock);
+
+       if (cx == NULL) {
+               /* Couldn't find a device registered
+                  on that minor, shouldn't happen! */
+               printk(KERN_WARNING "No cx18 device found on minor %d\n",
+                               minor);
+               return -ENXIO;
+       }
+
+       mutex_lock(&cx->serialize_lock);
+       if (cx18_init_on_first_open(cx)) {
+               CX18_ERR("Failed to initialize on minor %d\n", minor);
+               mutex_unlock(&cx->serialize_lock);
+               return -ENXIO;
+       }
+       res = cx18_serialized_open(s, filp);
+       mutex_unlock(&cx->serialize_lock);
+       return res;
+}
+
+void cx18_mute(struct cx18 *cx)
+{
+       if (atomic_read(&cx->capturing))
+               cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
+                               cx18_find_handle(cx), 1);
+       CX18_DEBUG_INFO("Mute\n");
+}
+
+void cx18_unmute(struct cx18 *cx)
+{
+       if (atomic_read(&cx->capturing)) {
+               cx18_msleep_timeout(100, 0);
+               cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2,
+                               cx18_find_handle(cx), 12);
+               cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
+                               cx18_find_handle(cx), 0);
+       }
+       CX18_DEBUG_INFO("Unmute\n");
+}
diff --git a/drivers/media/video/cx18/cx18-fileops.h b/drivers/media/video/cx18/cx18-fileops.h
new file mode 100644 (file)
index 0000000..16cdafb
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *  cx18 file operation functions
+ *
+ *  Derived from ivtv-fileops.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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
+ */
+
+/* Testing/Debugging */
+int cx18_v4l2_open(struct inode *inode, struct file *filp);
+ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
+                     loff_t *pos);
+ssize_t cx18_v4l2_write(struct file *filp, const char __user *buf, size_t count,
+                      loff_t *pos);
+int cx18_v4l2_close(struct inode *inode, struct file *filp);
+unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait);
+int cx18_start_capture(struct cx18_open_id *id);
+void cx18_stop_capture(struct cx18_open_id *id, int gop_end);
+void cx18_mute(struct cx18 *cx);
+void cx18_unmute(struct cx18 *cx);
+
+/* Utilities */
+
+/* Try to claim a stream for the filehandle. Return 0 on success,
+   -EBUSY if stream already claimed. Once a stream is claimed, it
+   remains claimed until the associated filehandle is closed. */
+int cx18_claim_stream(struct cx18_open_id *id, int type);
+
+/* Release a previously claimed stream. */
+void cx18_release_stream(struct cx18_stream *s);
diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c
new file mode 100644 (file)
index 0000000..2694ce3
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ *  cx18 firmware functions
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 "cx18-driver.h"
+#include "cx18-scb.h"
+#include "cx18-irq.h"
+#include "cx18-firmware.h"
+#include "cx18-cards.h"
+#include <linux/firmware.h>
+
+#define CX18_PROC_SOFT_RESET           0xc70010
+#define CX18_DDR_SOFT_RESET            0xc70014
+#define CX18_CLOCK_SELECT1             0xc71000
+#define CX18_CLOCK_SELECT2             0xc71004
+#define CX18_HALF_CLOCK_SELECT1        0xc71008
+#define CX18_HALF_CLOCK_SELECT2        0xc7100C
+#define CX18_CLOCK_POLARITY1           0xc71010
+#define CX18_CLOCK_POLARITY2           0xc71014
+#define CX18_ADD_DELAY_ENABLE1         0xc71018
+#define CX18_ADD_DELAY_ENABLE2         0xc7101C
+#define CX18_CLOCK_ENABLE1             0xc71020
+#define CX18_CLOCK_ENABLE2             0xc71024
+
+#define CX18_REG_BUS_TIMEOUT_EN        0xc72024
+
+#define CX18_AUDIO_ENABLE              0xc72014
+#define CX18_REG_BUS_TIMEOUT_EN        0xc72024
+
+#define CX18_FAST_CLOCK_PLL_INT        0xc78000
+#define CX18_FAST_CLOCK_PLL_FRAC       0xc78004
+#define CX18_FAST_CLOCK_PLL_POST       0xc78008
+#define CX18_FAST_CLOCK_PLL_PRESCALE   0xc7800C
+#define CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH 0xc78010
+
+#define CX18_SLOW_CLOCK_PLL_INT        0xc78014
+#define CX18_SLOW_CLOCK_PLL_FRAC       0xc78018
+#define CX18_SLOW_CLOCK_PLL_POST       0xc7801C
+#define CX18_MPEG_CLOCK_PLL_INT                0xc78040
+#define CX18_MPEG_CLOCK_PLL_FRAC       0xc78044
+#define CX18_MPEG_CLOCK_PLL_POST       0xc78048
+#define CX18_PLL_POWER_DOWN            0xc78088
+#define CX18_SW1_INT_STATUS             0xc73104
+#define CX18_SW1_INT_ENABLE_PCI         0xc7311C
+#define CX18_SW2_INT_SET                0xc73140
+#define CX18_SW2_INT_STATUS             0xc73144
+#define CX18_ADEC_CONTROL              0xc78120
+
+#define CX18_DDR_REQUEST_ENABLE        0xc80000
+#define CX18_DDR_CHIP_CONFIG           0xc80004
+#define CX18_DDR_REFRESH               0xc80008
+#define CX18_DDR_TIMING1               0xc8000C
+#define CX18_DDR_TIMING2               0xc80010
+#define CX18_DDR_POWER_REG             0xc8001C
+
+#define CX18_DDR_TUNE_LANE             0xc80048
+#define CX18_DDR_INITIAL_EMRS          0xc80054
+#define CX18_DDR_MB_PER_ROW_7          0xc8009C
+#define CX18_DDR_BASE_63_ADDR          0xc804FC
+
+#define CX18_WMB_CLIENT02              0xc90108
+#define CX18_WMB_CLIENT05              0xc90114
+#define CX18_WMB_CLIENT06              0xc90118
+#define CX18_WMB_CLIENT07              0xc9011C
+#define CX18_WMB_CLIENT08              0xc90120
+#define CX18_WMB_CLIENT09              0xc90124
+#define CX18_WMB_CLIENT10              0xc90128
+#define CX18_WMB_CLIENT11              0xc9012C
+#define CX18_WMB_CLIENT12              0xc90130
+#define CX18_WMB_CLIENT13              0xc90134
+#define CX18_WMB_CLIENT14              0xc90138
+
+#define CX18_DSP0_INTERRUPT_MASK       0xd0004C
+
+/* Encoder/decoder firmware sizes */
+#define CX18_FW_CPU_SIZE               (174716)
+#define CX18_FW_APU_SIZE               (141200)
+
+#define APU_ROM_SYNC1 0x6D676553 /* "mgeS" */
+#define APU_ROM_SYNC2 0x72646548 /* "rdeH" */
+
+struct cx18_apu_rom_seghdr {
+       u32 sync1;
+       u32 sync2;
+       u32 addr;
+       u32 size;
+};
+
+static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx, long size)
+{
+       const struct firmware *fw = NULL;
+       int retries = 3;
+       int i, j;
+       u32 __iomem *dst = (u32 __iomem *)mem;
+       const u32 *src;
+
+retry:
+       if (!retries || request_firmware(&fw, fn, &cx->dev->dev)) {
+               CX18_ERR("Unable to open firmware %s (must be %ld bytes)\n",
+                               fn, size);
+               CX18_ERR("Did you put the firmware in the hotplug firmware directory?\n");
+               return -ENOMEM;
+       }
+
+       src = (const u32 *)fw->data;
+
+       if (fw->size != size) {
+               /* Due to race conditions in firmware loading (esp. with
+                  udev <0.95) the wrong file was sometimes loaded. So we check
+                  filesizes to see if at least the right-sized file was
+                  loaded. If not, then we retry. */
+               CX18_INFO("retry: file loaded was not %s (expected size %ld, got %zd)\n",
+                               fn, size, fw->size);
+               release_firmware(fw);
+               retries--;
+               goto retry;
+       }
+       for (i = 0; i < fw->size; i += 4096) {
+               setup_page(i);
+               for (j = i; j < fw->size && j < i + 4096; j += 4) {
+                       /* no need for endianness conversion on the ppc */
+                       __raw_writel(*src, dst);
+                       if (__raw_readl(dst) != *src) {
+                               CX18_ERR("Mismatch at offset %x\n", i);
+                               release_firmware(fw);
+                               return -EIO;
+                       }
+                       dst++;
+                       src++;
+               }
+       }
+       if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
+               CX18_INFO("loaded %s firmware (%zd bytes)\n", fn, fw->size);
+       release_firmware(fw);
+       return size;
+}
+
+static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx, long size)
+{
+       const struct firmware *fw = NULL;
+       int retries = 3;
+       int i, j;
+       const u32 *src;
+       struct cx18_apu_rom_seghdr seghdr;
+       const u8 *vers;
+       u32 offset = 0;
+       u32 apu_version = 0;
+       int sz;
+
+retry:
+       if (!retries || request_firmware(&fw, fn, &cx->dev->dev)) {
+               CX18_ERR("unable to open firmware %s (must be %ld bytes)\n",
+                               fn, size);
+               CX18_ERR("did you put the firmware in the hotplug firmware directory?\n");
+               return -ENOMEM;
+       }
+
+       src = (const u32 *)fw->data;
+       vers = fw->data + sizeof(seghdr);
+       sz = fw->size;
+
+       if (fw->size != size) {
+               /* Due to race conditions in firmware loading (esp. with
+                  udev <0.95) the wrong file was sometimes loaded. So we check
+                  filesizes to see if at least the right-sized file was
+                  loaded. If not, then we retry. */
+               CX18_INFO("retry: file loaded was not %s (expected size %ld, got %zd)\n",
+                              fn, size, fw->size);
+               release_firmware(fw);
+               retries--;
+               goto retry;
+       }
+       apu_version = (vers[0] << 24) | (vers[4] << 16) | vers[32];
+       while (offset + sizeof(seghdr) < size) {
+               /* TODO: byteswapping */
+               memcpy(&seghdr, src + offset / 4, sizeof(seghdr));
+               offset += sizeof(seghdr);
+               if (seghdr.sync1 != APU_ROM_SYNC1 ||
+                   seghdr.sync2 != APU_ROM_SYNC2) {
+                       offset += seghdr.size;
+                       continue;
+               }
+               CX18_DEBUG_INFO("load segment %x-%x\n", seghdr.addr,
+                               seghdr.addr + seghdr.size - 1);
+               if (offset + seghdr.size > sz)
+                       break;
+               for (i = 0; i < seghdr.size; i += 4096) {
+                       setup_page(offset + i);
+                       for (j = i; j < seghdr.size && j < i + 4096; j += 4) {
+                               /* no need for endianness conversion on the ppc */
+                               __raw_writel(src[(offset + j) / 4], dst + seghdr.addr + j);
+                               if (__raw_readl(dst + seghdr.addr + j) != src[(offset + j) / 4]) {
+                                       CX18_ERR("Mismatch at offset %x\n", offset + j);
+                                       release_firmware(fw);
+                                       return -EIO;
+                               }
+                       }
+               }
+               offset += seghdr.size;
+       }
+       if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
+               CX18_INFO("loaded %s firmware V%08x (%zd bytes)\n",
+                               fn, apu_version, fw->size);
+       release_firmware(fw);
+       /* Clear bit0 for APU to start from 0 */
+       write_reg(read_reg(0xc72030) & ~1, 0xc72030);
+       return size;
+}
+
+void cx18_halt_firmware(struct cx18 *cx)
+{
+       CX18_DEBUG_INFO("Preparing for firmware halt.\n");
+       write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
+       write_reg(0x00020002, CX18_ADEC_CONTROL);
+}
+
+void cx18_init_power(struct cx18 *cx, int lowpwr)
+{
+       /* power-down Spare and AOM PLLs */
+       /* power-up fast, slow and mpeg PLLs */
+       write_reg(0x00000008, CX18_PLL_POWER_DOWN);
+
+       /* ADEC out of sleep */
+       write_reg(0x00020000, CX18_ADEC_CONTROL);
+
+       /* The fast clock is at 200/245 MHz */
+       write_reg(lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT);
+       write_reg(lowpwr ? 0x1EFBF37 : 0x038E3D7, CX18_FAST_CLOCK_PLL_FRAC);
+
+       write_reg(2, CX18_FAST_CLOCK_PLL_POST);
+       write_reg(1, CX18_FAST_CLOCK_PLL_PRESCALE);
+       write_reg(4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH);
+
+       /* set slow clock to 125/120 MHz */
+       write_reg(lowpwr ? 0x11 : 0x10, CX18_SLOW_CLOCK_PLL_INT);
+       write_reg(lowpwr ? 0xEBAF05 : 0x18618A8, CX18_SLOW_CLOCK_PLL_FRAC);
+       write_reg(4, CX18_SLOW_CLOCK_PLL_POST);
+
+       /* mpeg clock pll 54MHz */
+       write_reg(0xF, CX18_MPEG_CLOCK_PLL_INT);
+       write_reg(0x2BCFEF, CX18_MPEG_CLOCK_PLL_FRAC);
+       write_reg(8, CX18_MPEG_CLOCK_PLL_POST);
+
+       /* Defaults */
+       /* APU = SC or SC/2 = 125/62.5 */
+       /* EPU = SC = 125 */
+       /* DDR = FC = 180 */
+       /* ENC = SC = 125 */
+       /* AI1 = SC = 125 */
+       /* VIM2 = disabled */
+       /* PCI = FC/2 = 90 */
+       /* AI2 = disabled */
+       /* DEMUX = disabled */
+       /* AO = SC/2 = 62.5 */
+       /* SER = 54MHz */
+       /* VFC = disabled */
+       /* USB = disabled */
+
+       write_reg(lowpwr ? 0xFFFF0020 : 0x00060004, CX18_CLOCK_SELECT1);
+       write_reg(lowpwr ? 0xFFFF0004 : 0x00060006, CX18_CLOCK_SELECT2);
+
+       write_reg(0xFFFF0002, CX18_HALF_CLOCK_SELECT1);
+       write_reg(0xFFFF0104, CX18_HALF_CLOCK_SELECT2);
+
+       write_reg(0xFFFF9026, CX18_CLOCK_ENABLE1);
+       write_reg(0xFFFF3105, CX18_CLOCK_ENABLE2);
+}
+
+void cx18_init_memory(struct cx18 *cx)
+{
+       cx18_msleep_timeout(10, 0);
+       write_reg(0x10000, CX18_DDR_SOFT_RESET);
+       cx18_msleep_timeout(10, 0);
+
+       write_reg(cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG);
+
+       cx18_msleep_timeout(10, 0);
+
+       write_reg(cx->card->ddr.refresh, CX18_DDR_REFRESH);
+       write_reg(cx->card->ddr.timing1, CX18_DDR_TIMING1);
+       write_reg(cx->card->ddr.timing2, CX18_DDR_TIMING2);
+
+       cx18_msleep_timeout(10, 0);
+
+       /* Initialize DQS pad time */
+       write_reg(cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE);
+       write_reg(cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS);
+
+       cx18_msleep_timeout(10, 0);
+
+       write_reg(0x20000, CX18_DDR_SOFT_RESET);
+       cx18_msleep_timeout(10, 0);
+
+       /* use power-down mode when idle */
+       write_reg(0x00000010, CX18_DDR_POWER_REG);
+
+       write_reg(0x10001, CX18_REG_BUS_TIMEOUT_EN);
+
+       write_reg(0x48, CX18_DDR_MB_PER_ROW_7);
+       write_reg(0xE0000, CX18_DDR_BASE_63_ADDR);
+
+       write_reg(0x00000101, CX18_WMB_CLIENT02);  /* AO */
+       write_reg(0x00000101, CX18_WMB_CLIENT09);  /* AI2 */
+       write_reg(0x00000101, CX18_WMB_CLIENT05);  /* VIM1 */
+       write_reg(0x00000101, CX18_WMB_CLIENT06);  /* AI1 */
+       write_reg(0x00000101, CX18_WMB_CLIENT07);  /* 3D comb */
+       write_reg(0x00000101, CX18_WMB_CLIENT10);  /* ME */
+       write_reg(0x00000101, CX18_WMB_CLIENT12);  /* ENC */
+       write_reg(0x00000101, CX18_WMB_CLIENT13);  /* PK */
+       write_reg(0x00000101, CX18_WMB_CLIENT11);  /* RC */
+       write_reg(0x00000101, CX18_WMB_CLIENT14);  /* AVO */
+}
+
+int cx18_firmware_init(struct cx18 *cx)
+{
+       /* Allow chip to control CLKRUN */
+       write_reg(0x5, CX18_DSP0_INTERRUPT_MASK);
+
+       write_reg(0x000F000F, CX18_PROC_SOFT_RESET); /* stop the fw */
+
+       cx18_msleep_timeout(1, 0);
+
+       sw1_irq_enable(IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
+       sw2_irq_enable(IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
+
+       /* Only if the processor is not running */
+       if (read_reg(CX18_PROC_SOFT_RESET) & 8) {
+               int sz = load_apu_fw_direct("v4l-cx23418-apu.fw",
+                              cx->enc_mem, cx, CX18_FW_APU_SIZE);
+
+               sz = sz <= 0 ? sz : load_cpu_fw_direct("v4l-cx23418-cpu.fw",
+                                       cx->enc_mem, cx, CX18_FW_CPU_SIZE);
+
+               if (sz > 0) {
+                       int retries = 0;
+
+                       /* start the CPU */
+                       write_reg(0x00080000, CX18_PROC_SOFT_RESET);
+                       while (retries++ < 50) { /* Loop for max 500mS */
+                               if ((read_reg(CX18_PROC_SOFT_RESET) & 1) == 0)
+                                       break;
+                               cx18_msleep_timeout(10, 0);
+                       }
+                       cx18_msleep_timeout(200, 0);
+                       if (retries == 51) {
+                               CX18_ERR("Could not start the CPU\n");
+                               return -EIO;
+                       }
+               }
+               if (sz <= 0)
+                       return -EIO;
+       }
+       /* initialize GPIO */
+       write_reg(0x14001400, 0xC78110);
+       return 0;
+}
diff --git a/drivers/media/video/cx18/cx18-firmware.h b/drivers/media/video/cx18/cx18-firmware.h
new file mode 100644 (file)
index 0000000..38d4c05
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  cx18 firmware functions
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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
+ */
+
+int cx18_firmware_init(struct cx18 *cx);
+void cx18_halt_firmware(struct cx18 *cx);
+void cx18_init_memory(struct cx18 *cx);
+void cx18_init_power(struct cx18 *cx, int lowpwr);
diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c
new file mode 100644 (file)
index 0000000..19253e6
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ *  cx18 gpio functions
+ *
+ *  Derived from ivtv-gpio.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 "cx18-driver.h"
+#include "cx18-cards.h"
+#include "cx18-gpio.h"
+#include "tuner-xc2028.h"
+
+/********************* GPIO stuffs *********************/
+
+/* GPIO registers */
+#define CX18_REG_GPIO_IN     0xc72010
+#define CX18_REG_GPIO_OUT1   0xc78100
+#define CX18_REG_GPIO_DIR1   0xc78108
+#define CX18_REG_GPIO_OUT2   0xc78104
+#define CX18_REG_GPIO_DIR2   0xc7810c
+
+/*
+ * HVR-1600 GPIO pins, courtesy of Hauppauge:
+ *
+ * gpio0: zilog ir process reset pin
+ * gpio1: zilog programming pin (you should never use this)
+ * gpio12: cx24227 reset pin
+ * gpio13: cs5345 reset pin
+*/
+
+void cx18_gpio_init(struct cx18 *cx)
+{
+       if (cx->card->gpio_init.direction == 0)
+               return;
+
+       CX18_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n",
+                  read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_OUT1));
+
+       /* init output data then direction */
+       write_reg(cx->card->gpio_init.direction << 16, CX18_REG_GPIO_DIR1);
+       write_reg(0, CX18_REG_GPIO_DIR2);
+       write_reg((cx->card->gpio_init.direction << 16) |
+                       cx->card->gpio_init.initial_value, CX18_REG_GPIO_OUT1);
+       write_reg(0, CX18_REG_GPIO_OUT2);
+}
+
+/* Xceive tuner reset function */
+int cx18_reset_tuner_gpio(void *dev, int cmd, int value)
+{
+       struct i2c_algo_bit_data *algo = dev;
+       struct cx18 *cx = algo->data;
+/*     int curdir, curout;*/
+
+       if (cmd != XC2028_TUNER_RESET)
+               return 0;
+       CX18_DEBUG_INFO("Resetting tuner\n");
+       return 0;
+}
diff --git a/drivers/media/video/cx18/cx18-gpio.h b/drivers/media/video/cx18/cx18-gpio.h
new file mode 100644 (file)
index 0000000..41bac88
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  cx18 gpio functions
+ *
+ *  Derived from ivtv-gpio.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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
+ */
+
+void cx18_gpio_init(struct cx18 *cx);
+int cx18_reset_tuner_gpio(void *dev, int cmd, int value);
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c
new file mode 100644 (file)
index 0000000..18c88d1
--- /dev/null
@@ -0,0 +1,431 @@
+/*
+ *  cx18 I2C functions
+ *
+ *  Derived from ivtv-i2c.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 "cx18-driver.h"
+#include "cx18-cards.h"
+#include "cx18-gpio.h"
+#include "cx18-av-core.h"
+
+#include <media/ir-kbd-i2c.h>
+
+#define CX18_REG_I2C_1_WR   0xf15000
+#define CX18_REG_I2C_1_RD   0xf15008
+#define CX18_REG_I2C_2_WR   0xf25100
+#define CX18_REG_I2C_2_RD   0xf25108
+
+#define SETSCL_BIT      0x0001
+#define SETSDL_BIT      0x0002
+#define GETSCL_BIT      0x0004
+#define GETSDL_BIT      0x0008
+
+#ifndef I2C_ADAP_CLASS_TV_ANALOG
+#define I2C_ADAP_CLASS_TV_ANALOG I2C_CLASS_TV_ANALOG
+#endif
+
+#define CX18_CS5345_I2C_ADDR           0x4c
+
+/* This array should match the CX18_HW_ defines */
+static const u8 hw_driverids[] = {
+       I2C_DRIVERID_TUNER,
+       I2C_DRIVERID_TVEEPROM,
+       I2C_DRIVERID_CS5345,
+       0,              /* CX18_HW_GPIO dummy driver ID */
+       0               /* CX18_HW_CX23418 dummy driver ID */
+};
+
+/* This array should match the CX18_HW_ defines */
+static const u8 hw_addrs[] = {
+       0,
+       0,
+       CX18_CS5345_I2C_ADDR,
+       0,              /* CX18_HW_GPIO dummy driver ID */
+       0,              /* CX18_HW_CX23418 dummy driver ID */
+};
+
+/* This array should match the CX18_HW_ defines */
+/* This might well become a card-specific array */
+static const u8 hw_bus[] = {
+       0,
+       0,
+       0,
+       0,              /* CX18_HW_GPIO dummy driver ID */
+       0,              /* CX18_HW_CX23418 dummy driver ID */
+};
+
+/* This array should match the CX18_HW_ defines */
+static const char * const hw_drivernames[] = {
+       "tuner",
+       "tveeprom",
+       "cs5345",
+       "gpio",
+       "cx23418",
+};
+
+int cx18_i2c_register(struct cx18 *cx, unsigned idx)
+{
+       struct i2c_board_info info;
+       struct i2c_client *c;
+       u8 id, bus;
+       int i;
+
+       CX18_DEBUG_I2C("i2c client register\n");
+       if (idx >= ARRAY_SIZE(hw_driverids) || hw_driverids[idx] == 0)
+               return -1;
+       id = hw_driverids[idx];
+       bus = hw_bus[idx];
+       memset(&info, 0, sizeof(info));
+       strlcpy(info.driver_name, hw_drivernames[idx],
+                       sizeof(info.driver_name));
+       info.addr = hw_addrs[idx];
+       for (i = 0; i < I2C_CLIENTS_MAX; i++)
+               if (cx->i2c_clients[i] == NULL)
+                       break;
+
+       if (i == I2C_CLIENTS_MAX) {
+               CX18_ERR("insufficient room for new I2C client!\n");
+               return -ENOMEM;
+       }
+
+       if (id != I2C_DRIVERID_TUNER) {
+               c = i2c_new_device(&cx->i2c_adap[bus], &info);
+               if (c->driver == NULL)
+                       i2c_unregister_device(c);
+               else
+                       cx->i2c_clients[i] = c;
+               return cx->i2c_clients[i] ? 0 : -ENODEV;
+       }
+
+       /* special tuner handling */
+       c = i2c_new_probed_device(&cx->i2c_adap[1], &info, cx->card_i2c->radio);
+       if (c && c->driver == NULL)
+               i2c_unregister_device(c);
+       else if (c)
+               cx->i2c_clients[i++] = c;
+       c = i2c_new_probed_device(&cx->i2c_adap[1], &info, cx->card_i2c->demod);
+       if (c && c->driver == NULL)
+               i2c_unregister_device(c);
+       else if (c)
+               cx->i2c_clients[i++] = c;
+       c = i2c_new_probed_device(&cx->i2c_adap[1], &info, cx->card_i2c->tv);
+       if (c && c->driver == NULL)
+               i2c_unregister_device(c);
+       else if (c)
+               cx->i2c_clients[i++] = c;
+       return 0;
+}
+
+static int attach_inform(struct i2c_client *client)
+{
+       return 0;
+}
+
+static int detach_inform(struct i2c_client *client)
+{
+       int i;
+       struct cx18 *cx = (struct cx18 *)i2c_get_adapdata(client->adapter);
+
+       CX18_DEBUG_I2C("i2c client detach\n");
+       for (i = 0; i < I2C_CLIENTS_MAX; i++) {
+               if (cx->i2c_clients[i] == client) {
+                       cx->i2c_clients[i] = NULL;
+                       break;
+               }
+       }
+       CX18_DEBUG_I2C("i2c detach [client=%s,%s]\n",
+                  client->name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed");
+
+       return 0;
+}
+
+static void cx18_setscl(void *data, int state)
+{
+       struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
+       int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
+       u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
+       u32 r = read_reg(addr);
+
+       if (state)
+               write_reg_sync(r | SETSCL_BIT, addr);
+       else
+               write_reg_sync(r & ~SETSCL_BIT, addr);
+}
+
+static void cx18_setsda(void *data, int state)
+{
+       struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
+       int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
+       u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
+       u32 r = read_reg(addr);
+
+       if (state)
+               write_reg_sync(r | SETSDL_BIT, addr);
+       else
+               write_reg_sync(r & ~SETSDL_BIT, addr);
+}
+
+static int cx18_getscl(void *data)
+{
+       struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
+       int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
+       u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
+
+       return read_reg(addr) & GETSCL_BIT;
+}
+
+static int cx18_getsda(void *data)
+{
+       struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
+       int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
+       u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
+
+       return read_reg(addr) & GETSDL_BIT;
+}
+
+/* template for i2c-bit-algo */
+static struct i2c_adapter cx18_i2c_adap_template = {
+       .name = "cx18 i2c driver",
+       .id = I2C_HW_B_CX2341X,
+       .algo = NULL,                   /* set by i2c-algo-bit */
+       .algo_data = NULL,              /* filled from template */
+       .client_register = attach_inform,
+       .client_unregister = detach_inform,
+       .owner = THIS_MODULE,
+};
+
+#define CX18_SCL_PERIOD (10) /* usecs. 10 usec is period for a 100 KHz clock */
+#define CX18_ALGO_BIT_TIMEOUT (2) /* seconds */
+
+static struct i2c_algo_bit_data cx18_i2c_algo_template = {
+       .setsda         = cx18_setsda,
+       .setscl         = cx18_setscl,
+       .getsda         = cx18_getsda,
+       .getscl         = cx18_getscl,
+       .udelay         = CX18_SCL_PERIOD/2,       /* 1/2 clock period in usec*/
+       .timeout        = CX18_ALGO_BIT_TIMEOUT*HZ /* jiffies */
+};
+
+static struct i2c_client cx18_i2c_client_template = {
+       .name = "cx18 internal",
+};
+
+int cx18_call_i2c_client(struct cx18 *cx, int addr, unsigned cmd, void *arg)
+{
+       struct i2c_client *client;
+       int retval;
+       int i;
+
+       CX18_DEBUG_I2C("call_i2c_client addr=%02x\n", addr);
+       for (i = 0; i < I2C_CLIENTS_MAX; i++) {
+               client = cx->i2c_clients[i];
+               if (client == NULL || client->driver == NULL ||
+                               client->driver->command == NULL)
+                       continue;
+               if (addr == client->addr) {
+                       retval = client->driver->command(client, cmd, arg);
+                       return retval;
+               }
+       }
+       if (cmd != VIDIOC_G_CHIP_IDENT)
+               CX18_ERR("i2c addr 0x%02x not found for cmd 0x%x!\n",
+                              addr, cmd);
+       return -ENODEV;
+}
+
+/* Find the i2c device based on the driver ID and return
+   its i2c address or -ENODEV if no matching device was found. */
+static int cx18_i2c_id_addr(struct cx18 *cx, u32 id)
+{
+       struct i2c_client *client;
+       int retval = -ENODEV;
+       int i;
+
+       for (i = 0; i < I2C_CLIENTS_MAX; i++) {
+               client = cx->i2c_clients[i];
+               if (client == NULL || client->driver == NULL)
+                       continue;
+               if (id == client->driver->id) {
+                       retval = client->addr;
+                       break;
+               }
+       }
+       return retval;
+}
+
+/* Find the i2c device name matching the DRIVERID */
+static const char *cx18_i2c_id_name(u32 id)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
+               if (hw_driverids[i] == id)
+                       return hw_drivernames[i];
+       return "unknown device";
+}
+
+/* Find the i2c device name matching the CX18_HW_ flag */
+static const char *cx18_i2c_hw_name(u32 hw)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
+               if (1 << i == hw)
+                       return hw_drivernames[i];
+       return "unknown device";
+}
+
+/* Find the i2c device matching the CX18_HW_ flag and return
+   its i2c address or -ENODEV if no matching device was found. */
+int cx18_i2c_hw_addr(struct cx18 *cx, u32 hw)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)
+               if (1 << i == hw)
+                       return cx18_i2c_id_addr(cx, hw_driverids[i]);
+       return -ENODEV;
+}
+
+/* Calls i2c device based on CX18_HW_ flag. If hw == 0, then do nothing.
+   If hw == CX18_HW_GPIO then call the gpio handler. */
+int cx18_i2c_hw(struct cx18 *cx, u32 hw, unsigned int cmd, void *arg)
+{
+       int addr;
+
+       if (hw == CX18_HW_GPIO || hw == 0)
+               return 0;
+       if (hw == CX18_HW_CX23418)
+               return cx18_av_cmd(cx, cmd, arg);
+
+       addr = cx18_i2c_hw_addr(cx, hw);
+       if (addr < 0) {
+               CX18_ERR("i2c hardware 0x%08x (%s) not found for cmd 0x%x!\n",
+                              hw, cx18_i2c_hw_name(hw), cmd);
+               return addr;
+       }
+       return cx18_call_i2c_client(cx, addr, cmd, arg);
+}
+
+/* Calls i2c device based on I2C driver ID. */
+int cx18_i2c_id(struct cx18 *cx, u32 id, unsigned int cmd, void *arg)
+{
+       int addr;
+
+       addr = cx18_i2c_id_addr(cx, id);
+       if (addr < 0) {
+               if (cmd != VIDIOC_G_CHIP_IDENT)
+                       CX18_ERR("i2c ID 0x%08x (%s) not found for cmd 0x%x!\n",
+                               id, cx18_i2c_id_name(id), cmd);
+               return addr;
+       }
+       return cx18_call_i2c_client(cx, addr, cmd, arg);
+}
+
+/* broadcast cmd for all I2C clients and for the gpio subsystem */
+void cx18_call_i2c_clients(struct cx18 *cx, unsigned int cmd, void *arg)
+{
+       if (cx->i2c_adap[0].algo == NULL || cx->i2c_adap[1].algo == NULL) {
+               CX18_ERR("adapter is not set\n");
+               return;
+       }
+       cx18_av_cmd(cx, cmd, arg);
+       i2c_clients_command(&cx->i2c_adap[0], cmd, arg);
+       i2c_clients_command(&cx->i2c_adap[1], cmd, arg);
+}
+
+/* init + register i2c algo-bit adapter */
+int init_cx18_i2c(struct cx18 *cx)
+{
+       int i;
+       CX18_DEBUG_I2C("i2c init\n");
+
+       for (i = 0; i < 2; i++) {
+               memcpy(&cx->i2c_adap[i], &cx18_i2c_adap_template,
+                       sizeof(struct i2c_adapter));
+               memcpy(&cx->i2c_algo[i], &cx18_i2c_algo_template,
+                       sizeof(struct i2c_algo_bit_data));
+               cx->i2c_algo_cb_data[i].cx = cx;
+               cx->i2c_algo_cb_data[i].bus_index = i;
+               cx->i2c_algo[i].data = &cx->i2c_algo_cb_data[i];
+               cx->i2c_adap[i].algo_data = &cx->i2c_algo[i];
+
+               sprintf(cx->i2c_adap[i].name + strlen(cx->i2c_adap[i].name),
+                               " #%d-%d", cx->num, i);
+               i2c_set_adapdata(&cx->i2c_adap[i], cx);
+
+               memcpy(&cx->i2c_client[i], &cx18_i2c_client_template,
+                       sizeof(struct i2c_client));
+               sprintf(cx->i2c_client[i].name +
+                               strlen(cx->i2c_client[i].name), "%d", i);
+               cx->i2c_client[i].adapter = &cx->i2c_adap[i];
+               cx->i2c_adap[i].dev.parent = &cx->dev->dev;
+       }
+
+       if (read_reg(CX18_REG_I2C_2_WR) != 0x0003c02f) {
+               /* Reset/Unreset I2C hardware block */
+               write_reg(0x10000000, 0xc71004); /* Clock select 220MHz */
+               write_reg_sync(0x10001000, 0xc71024); /* Clock Enable */
+       }
+       /* courtesy of Steven Toth <stoth@hauppauge.com> */
+       write_reg_sync(0x00c00000, 0xc7001c);
+       mdelay(10);
+       write_reg_sync(0x00c000c0, 0xc7001c);
+       mdelay(10);
+       write_reg_sync(0x00c00000, 0xc7001c);
+
+       write_reg_sync(0x00c00000, 0xc730c8); /* Set to edge-triggered intrs. */
+       write_reg_sync(0x00c00000, 0xc730c4); /* Clear any stale intrs */
+
+       /* Hw I2C1 Clock Freq ~100kHz */
+       write_reg_sync(0x00021c0f & ~4, CX18_REG_I2C_1_WR);
+       cx18_setscl(&cx->i2c_algo_cb_data[0], 1);
+       cx18_setsda(&cx->i2c_algo_cb_data[0], 1);
+
+       /* Hw I2C2 Clock Freq ~100kHz */
+       write_reg_sync(0x00021c0f & ~4, CX18_REG_I2C_2_WR);
+       cx18_setscl(&cx->i2c_algo_cb_data[1], 1);
+       cx18_setsda(&cx->i2c_algo_cb_data[1], 1);
+
+       return i2c_bit_add_bus(&cx->i2c_adap[0]) ||
+               i2c_bit_add_bus(&cx->i2c_adap[1]);
+}
+
+void exit_cx18_i2c(struct cx18 *cx)
+{
+       int i;
+       CX18_DEBUG_I2C("i2c exit\n");
+       write_reg(read_reg(CX18_REG_I2C_1_WR) | 4, CX18_REG_I2C_1_WR);
+       write_reg(read_reg(CX18_REG_I2C_2_WR) | 4, CX18_REG_I2C_2_WR);
+
+       for (i = 0; i < 2; i++) {
+               i2c_del_adapter(&cx->i2c_adap[i]);
+       }
+}
+
+/*
+   Hauppauge HVR1600 should have:
+   32 cx24227
+   98 unknown
+   a0 eeprom
+   c2 tuner
+   e? zilog ir
+   */
diff --git a/drivers/media/video/cx18/cx18-i2c.h b/drivers/media/video/cx18/cx18-i2c.h
new file mode 100644 (file)
index 0000000..113c3f9
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  cx18 I2C functions
+ *
+ *  Derived from ivtv-i2c.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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
+ */
+
+int cx18_i2c_hw_addr(struct cx18 *cx, u32 hw);
+int cx18_i2c_hw(struct cx18 *cx, u32 hw, unsigned int cmd, void *arg);
+int cx18_i2c_id(struct cx18 *cx, u32 id, unsigned int cmd, void *arg);
+int cx18_call_i2c_client(struct cx18 *cx, int addr, unsigned cmd, void *arg);
+void cx18_call_i2c_clients(struct cx18 *cx, unsigned int cmd, void *arg);
+int cx18_i2c_register(struct cx18 *cx, unsigned idx);
+
+/* init + register i2c algo-bit adapter */
+int init_cx18_i2c(struct cx18 *cx);
+void exit_cx18_i2c(struct cx18 *cx);
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
new file mode 100644 (file)
index 0000000..dbdcb86
--- /dev/null
@@ -0,0 +1,851 @@
+/*
+ *  cx18 ioctl system call
+ *
+ *  Derived from ivtv-ioctl.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 "cx18-driver.h"
+#include "cx18-version.h"
+#include "cx18-mailbox.h"
+#include "cx18-i2c.h"
+#include "cx18-queue.h"
+#include "cx18-fileops.h"
+#include "cx18-vbi.h"
+#include "cx18-audio.h"
+#include "cx18-video.h"
+#include "cx18-streams.h"
+#include "cx18-ioctl.h"
+#include "cx18-gpio.h"
+#include "cx18-controls.h"
+#include "cx18-cards.h"
+#include "cx18-av-core.h"
+#include <media/tveeprom.h>
+#include <media/v4l2-chip-ident.h>
+#include <linux/i2c-id.h>
+
+u16 cx18_service2vbi(int type)
+{
+       switch (type) {
+       case V4L2_SLICED_TELETEXT_B:
+               return CX18_SLICED_TYPE_TELETEXT_B;
+       case V4L2_SLICED_CAPTION_525:
+               return CX18_SLICED_TYPE_CAPTION_525;
+       case V4L2_SLICED_WSS_625:
+               return CX18_SLICED_TYPE_WSS_625;
+       case V4L2_SLICED_VPS:
+               return CX18_SLICED_TYPE_VPS;
+       default:
+               return 0;
+       }
+}
+
+static int valid_service_line(int field, int line, int is_pal)
+{
+       return (is_pal && line >= 6 && (line != 23 || field == 0)) ||
+              (!is_pal && line >= 10 && line < 22);
+}
+
+static u16 select_service_from_set(int field, int line, u16 set, int is_pal)
+{
+       u16 valid_set = (is_pal ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525);
+       int i;
+
+       set = set & valid_set;
+       if (set == 0 || !valid_service_line(field, line, is_pal))
+               return 0;
+       if (!is_pal) {
+               if (line == 21 && (set & V4L2_SLICED_CAPTION_525))
+                       return V4L2_SLICED_CAPTION_525;
+       } else {
+               if (line == 16 && field == 0 && (set & V4L2_SLICED_VPS))
+                       return V4L2_SLICED_VPS;
+               if (line == 23 && field == 0 && (set & V4L2_SLICED_WSS_625))
+                       return V4L2_SLICED_WSS_625;
+               if (line == 23)
+                       return 0;
+       }
+       for (i = 0; i < 32; i++) {
+               if ((1 << i) & set)
+                       return 1 << i;
+       }
+       return 0;
+}
+
+void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
+{
+       u16 set = fmt->service_set;
+       int f, l;
+
+       fmt->service_set = 0;
+       for (f = 0; f < 2; f++) {
+               for (l = 0; l < 24; l++)
+                       fmt->service_lines[f][l] = select_service_from_set(f, l, set, is_pal);
+       }
+}
+
+static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
+{
+       int f, l;
+       u16 set = 0;
+
+       for (f = 0; f < 2; f++) {
+               for (l = 0; l < 24; l++) {
+                       fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal);
+                       set |= fmt->service_lines[f][l];
+               }
+       }
+       return set != 0;
+}
+
+u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt)
+{
+       int f, l;
+       u16 set = 0;
+
+       for (f = 0; f < 2; f++) {
+               for (l = 0; l < 24; l++)
+                       set |= fmt->service_lines[f][l];
+       }
+       return set;
+}
+
+static const struct {
+       v4l2_std_id  std;
+       char        *name;
+} enum_stds[] = {
+       { V4L2_STD_PAL_BG | V4L2_STD_PAL_H, "PAL-BGH" },
+       { V4L2_STD_PAL_DK,    "PAL-DK"    },
+       { V4L2_STD_PAL_I,     "PAL-I"     },
+       { V4L2_STD_PAL_M,     "PAL-M"     },
+       { V4L2_STD_PAL_N,     "PAL-N"     },
+       { V4L2_STD_PAL_Nc,    "PAL-Nc"    },
+       { V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H, "SECAM-BGH" },
+       { V4L2_STD_SECAM_DK,  "SECAM-DK"  },
+       { V4L2_STD_SECAM_L,   "SECAM-L"   },
+       { V4L2_STD_SECAM_LC,  "SECAM-L'"  },
+       { V4L2_STD_NTSC_M,    "NTSC-M"    },
+       { V4L2_STD_NTSC_M_JP, "NTSC-J"    },
+       { V4L2_STD_NTSC_M_KR, "NTSC-K"    },
+};
+
+static const struct v4l2_standard cx18_std_60hz = {
+       .frameperiod = {.numerator = 1001, .denominator = 30000},
+       .framelines = 525,
+};
+
+static const struct v4l2_standard cx18_std_50hz = {
+       .frameperiod = { .numerator = 1, .denominator = 25 },
+       .framelines = 625,
+};
+
+static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
+{
+       struct v4l2_register *regs = arg;
+       unsigned long flags;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       if (regs->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE)
+               return -EINVAL;
+
+       spin_lock_irqsave(&cx18_cards_lock, flags);
+       if (cmd == VIDIOC_DBG_G_REGISTER)
+               regs->val = read_enc(regs->reg);
+       else
+               write_enc(regs->val, regs->reg);
+       spin_unlock_irqrestore(&cx18_cards_lock, flags);
+       return 0;
+}
+
+static int cx18_get_fmt(struct cx18 *cx, int streamtype, struct v4l2_format *fmt)
+{
+       switch (fmt->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               fmt->fmt.pix.width = cx->params.width;
+               fmt->fmt.pix.height = cx->params.height;
+               fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+               fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
+               if (streamtype == CX18_ENC_STREAM_TYPE_YUV) {
+                       fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_HM12;
+                       /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
+                       fmt->fmt.pix.sizeimage =
+                               fmt->fmt.pix.height * fmt->fmt.pix.width +
+                               fmt->fmt.pix.height * (fmt->fmt.pix.width / 2);
+               } else {
+                       fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
+                       fmt->fmt.pix.sizeimage = 128 * 1024;
+               }
+               break;
+
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+               fmt->fmt.vbi.sampling_rate = 27000000;
+               fmt->fmt.vbi.offset = 248;
+               fmt->fmt.vbi.samples_per_line = cx->vbi.raw_decoder_line_size - 4;
+               fmt->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+               fmt->fmt.vbi.start[0] = cx->vbi.start[0];
+               fmt->fmt.vbi.start[1] = cx->vbi.start[1];
+               fmt->fmt.vbi.count[0] = fmt->fmt.vbi.count[1] = cx->vbi.count;
+               break;
+
+       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+       {
+               struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
+
+               vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
+               memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved));
+               memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines));
+
+               cx18_av_cmd(cx, VIDIOC_G_FMT, fmt);
+               vbifmt->service_set = cx18_get_service_set(vbifmt);
+               break;
+       }
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int cx18_try_or_set_fmt(struct cx18 *cx, int streamtype,
+               struct v4l2_format *fmt, int set_fmt)
+{
+       struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
+       u16 set;
+
+       /* set window size */
+       if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               int w = fmt->fmt.pix.width;
+               int h = fmt->fmt.pix.height;
+
+               if (w > 720)
+                       w = 720;
+               else if (w < 1)
+                       w = 1;
+               if (h > (cx->is_50hz ? 576 : 480))
+                       h = (cx->is_50hz ? 576 : 480);
+               else if (h < 2)
+                       h = 2;
+               cx18_get_fmt(cx, streamtype, fmt);
+               fmt->fmt.pix.width = w;
+               fmt->fmt.pix.height = h;
+
+               if (!set_fmt || (cx->params.width == w && cx->params.height == h))
+                       return 0;
+               if (atomic_read(&cx->capturing) > 0)
+                       return -EBUSY;
+
+               cx->params.width = w;
+               cx->params.height = h;
+               if (w != 720 || h != (cx->is_50hz ? 576 : 480))
+                       cx->params.video_temporal_filter = 0;
+               else
+                       cx->params.video_temporal_filter = 8;
+               cx18_av_cmd(cx, VIDIOC_S_FMT, fmt);
+               return cx18_get_fmt(cx, streamtype, fmt);
+       }
+
+       /* set raw VBI format */
+       if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+               if (set_fmt && streamtype == CX18_ENC_STREAM_TYPE_VBI &&
+                   cx->vbi.sliced_in->service_set &&
+                   atomic_read(&cx->capturing) > 0)
+                       return -EBUSY;
+               if (set_fmt) {
+                       cx->vbi.sliced_in->service_set = 0;
+                       cx18_av_cmd(cx, VIDIOC_S_FMT, &cx->vbi.in);
+               }
+               return cx18_get_fmt(cx, streamtype, fmt);
+       }
+
+       /* any else but sliced VBI capture is an error */
+       if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
+               return -EINVAL;
+
+       /* TODO: implement sliced VBI, for now silently return 0 */
+       return 0;
+
+       /* set sliced VBI capture format */
+       vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
+       memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved));
+
+       if (vbifmt->service_set)
+               cx18_expand_service_set(vbifmt, cx->is_50hz);
+       set = check_service_set(vbifmt, cx->is_50hz);
+       vbifmt->service_set = cx18_get_service_set(vbifmt);
+
+       if (!set_fmt)
+               return 0;
+       if (set == 0)
+               return -EINVAL;
+       if (atomic_read(&cx->capturing) > 0 && cx->vbi.sliced_in->service_set == 0)
+               return -EBUSY;
+       cx18_av_cmd(cx, VIDIOC_S_FMT, fmt);
+       memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in));
+       return 0;
+}
+
+static int cx18_debug_ioctls(struct file *filp, unsigned int cmd, void *arg)
+{
+       struct cx18_open_id *id = (struct cx18_open_id *)filp->private_data;
+       struct cx18 *cx = id->cx;
+       struct v4l2_register *reg = arg;
+
+       switch (cmd) {
+       /* ioctls to allow direct access to the encoder registers for testing */
+       case VIDIOC_DBG_G_REGISTER:
+               if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
+                       return cx18_cxc(cx, cmd, arg);
+               if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
+                       return cx18_i2c_id(cx, reg->match_chip, cmd, arg);
+               return cx18_call_i2c_client(cx, reg->match_chip, cmd, arg);
+
+       case VIDIOC_DBG_S_REGISTER:
+               if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
+                       return cx18_cxc(cx, cmd, arg);
+               if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
+                       return cx18_i2c_id(cx, reg->match_chip, cmd, arg);
+               return cx18_call_i2c_client(cx, reg->match_chip, cmd, arg);
+
+       case VIDIOC_G_CHIP_IDENT: {
+               struct v4l2_chip_ident *chip = arg;
+
+               chip->ident = V4L2_IDENT_NONE;
+               chip->revision = 0;
+               if (reg->match_type == V4L2_CHIP_MATCH_HOST) {
+                       if (v4l2_chip_match_host(reg->match_type, reg->match_chip)) {
+                               struct v4l2_chip_ident *chip = arg;
+
+                               chip->ident = V4L2_IDENT_CX23418;
+                       }
+                       return 0;
+               }
+               if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER)
+                       return cx18_i2c_id(cx, reg->match_chip, cmd, arg);
+               if (reg->match_type == V4L2_CHIP_MATCH_I2C_ADDR)
+                       return cx18_call_i2c_client(cx, reg->match_chip, cmd, arg);
+               return -EINVAL;
+       }
+
+       case VIDIOC_INT_S_AUDIO_ROUTING: {
+               struct v4l2_routing *route = arg;
+
+               cx18_audio_set_route(cx, route);
+               break;
+       }
+
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd, void *arg)
+{
+       struct cx18_open_id *id = NULL;
+
+       if (filp)
+               id = (struct cx18_open_id *)filp->private_data;
+
+       switch (cmd) {
+       case VIDIOC_G_PRIORITY:
+       {
+               enum v4l2_priority *p = arg;
+
+               *p = v4l2_prio_max(&cx->prio);
+               break;
+       }
+
+       case VIDIOC_S_PRIORITY:
+       {
+               enum v4l2_priority *prio = arg;
+
+               return v4l2_prio_change(&cx->prio, &id->prio, *prio);
+       }
+
+       case VIDIOC_QUERYCAP:{
+               struct v4l2_capability *vcap = arg;
+
+               memset(vcap, 0, sizeof(*vcap));
+               strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
+               strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
+               strlcpy(vcap->bus_info, pci_name(cx->dev), sizeof(vcap->bus_info));
+               vcap->version = CX18_DRIVER_VERSION;        /* version */
+               vcap->capabilities = cx->v4l2_cap;          /* capabilities */
+
+               /* reserved.. must set to 0! */
+               vcap->reserved[0] = vcap->reserved[1] =
+                       vcap->reserved[2] = vcap->reserved[3] = 0;
+               break;
+       }
+
+       case VIDIOC_ENUMAUDIO:{
+               struct v4l2_audio *vin = arg;
+
+               return cx18_get_audio_input(cx, vin->index, vin);
+       }
+
+       case VIDIOC_G_AUDIO:{
+               struct v4l2_audio *vin = arg;
+
+               vin->index = cx->audio_input;
+               return cx18_get_audio_input(cx, vin->index, vin);
+       }
+
+       case VIDIOC_S_AUDIO:{
+               struct v4l2_audio *vout = arg;
+
+               if (vout->index >= cx->nof_audio_inputs)
+                       return -EINVAL;
+               cx->audio_input = vout->index;
+               cx18_audio_set_io(cx);
+               break;
+       }
+
+       case VIDIOC_ENUMINPUT:{
+               struct v4l2_input *vin = arg;
+
+               /* set it to defaults from our table */
+               return cx18_get_input(cx, vin->index, vin);
+       }
+
+       case VIDIOC_TRY_FMT:
+       case VIDIOC_S_FMT: {
+               struct v4l2_format *fmt = arg;
+
+               return cx18_try_or_set_fmt(cx, id->type, fmt, cmd == VIDIOC_S_FMT);
+       }
+
+       case VIDIOC_G_FMT: {
+               struct v4l2_format *fmt = arg;
+               int type = fmt->type;
+
+               memset(fmt, 0, sizeof(*fmt));
+               fmt->type = type;
+               return cx18_get_fmt(cx, id->type, fmt);
+       }
+
+       case VIDIOC_CROPCAP: {
+               struct v4l2_cropcap *cropcap = arg;
+
+               if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                       return -EINVAL;
+               cropcap->bounds.top = cropcap->bounds.left = 0;
+               cropcap->bounds.width = 720;
+               cropcap->bounds.height = cx->is_50hz ? 576 : 480;
+               cropcap->pixelaspect.numerator = cx->is_50hz ? 59 : 10;
+               cropcap->pixelaspect.denominator = cx->is_50hz ? 54 : 11;
+               cropcap->defrect = cropcap->bounds;
+               return 0;
+       }
+
+       case VIDIOC_S_CROP: {
+               struct v4l2_crop *crop = arg;
+
+               if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                       return -EINVAL;
+               return cx18_av_cmd(cx, VIDIOC_S_CROP, arg);
+       }
+
+       case VIDIOC_G_CROP: {
+               struct v4l2_crop *crop = arg;
+
+               if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                       return -EINVAL;
+               return cx18_av_cmd(cx, VIDIOC_G_CROP, arg);
+       }
+
+       case VIDIOC_ENUM_FMT: {
+               static struct v4l2_fmtdesc formats[] = {
+                       { 0, 0, 0,
+                         "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12,
+                         { 0, 0, 0, 0 }
+                       },
+                       { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
+                         "MPEG", V4L2_PIX_FMT_MPEG,
+                         { 0, 0, 0, 0 }
+                       }
+               };
+               struct v4l2_fmtdesc *fmt = arg;
+               enum v4l2_buf_type type = fmt->type;
+
+               switch (type) {
+               case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               if (fmt->index > 1)
+                       return -EINVAL;
+               *fmt = formats[fmt->index];
+               fmt->type = type;
+               return 0;
+       }
+
+       case VIDIOC_G_INPUT:{
+               *(int *)arg = cx->active_input;
+               break;
+       }
+
+       case VIDIOC_S_INPUT:{
+               int inp = *(int *)arg;
+
+               if (inp < 0 || inp >= cx->nof_inputs)
+                       return -EINVAL;
+
+               if (inp == cx->active_input) {
+                       CX18_DEBUG_INFO("Input unchanged\n");
+                       break;
+               }
+               CX18_DEBUG_INFO("Changing input from %d to %d\n",
+                               cx->active_input, inp);
+
+               cx->active_input = inp;
+               /* Set the audio input to whatever is appropriate for the
+                  input type. */
+               cx->audio_input = cx->card->video_inputs[inp].audio_index;
+
+               /* prevent others from messing with the streams until
+                  we're finished changing inputs. */
+               cx18_mute(cx);
+               cx18_video_set_io(cx);
+               cx18_audio_set_io(cx);
+               cx18_unmute(cx);
+               break;
+       }
+
+       case VIDIOC_G_FREQUENCY:{
+               struct v4l2_frequency *vf = arg;
+
+               if (vf->tuner != 0)
+                       return -EINVAL;
+               cx18_call_i2c_clients(cx, cmd, arg);
+               break;
+       }
+
+       case VIDIOC_S_FREQUENCY:{
+               struct v4l2_frequency vf = *(struct v4l2_frequency *)arg;
+
+               if (vf.tuner != 0)
+                       return -EINVAL;
+
+               cx18_mute(cx);
+               CX18_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf.frequency);
+               cx18_call_i2c_clients(cx, cmd, &vf);
+               cx18_unmute(cx);
+               break;
+       }
+
+       case VIDIOC_ENUMSTD:{
+               struct v4l2_standard *vs = arg;
+               int idx = vs->index;
+
+               if (idx < 0 || idx >= ARRAY_SIZE(enum_stds))
+                       return -EINVAL;
+
+               *vs = (enum_stds[idx].std & V4L2_STD_525_60) ?
+                               cx18_std_60hz : cx18_std_50hz;
+               vs->index = idx;
+               vs->id = enum_stds[idx].std;
+               strlcpy(vs->name, enum_stds[idx].name, sizeof(vs->name));
+               break;
+       }
+
+       case VIDIOC_G_STD:{
+               *(v4l2_std_id *) arg = cx->std;
+               break;
+       }
+
+       case VIDIOC_S_STD: {
+               v4l2_std_id std = *(v4l2_std_id *) arg;
+
+               if ((std & V4L2_STD_ALL) == 0)
+                       return -EINVAL;
+
+               if (std == cx->std)
+                       break;
+
+               if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ||
+                   atomic_read(&cx->capturing) > 0) {
+                       /* Switching standard would turn off the radio or mess
+                          with already running streams, prevent that by
+                          returning EBUSY. */
+                       return -EBUSY;
+               }
+
+               cx->std = std;
+               cx->is_60hz = (std & V4L2_STD_525_60) ? 1 : 0;
+               cx->params.is_50hz = cx->is_50hz = !cx->is_60hz;
+               cx->params.width = 720;
+               cx->params.height = cx->is_50hz ? 576 : 480;
+               cx->vbi.count = cx->is_50hz ? 18 : 12;
+               cx->vbi.start[0] = cx->is_50hz ? 6 : 10;
+               cx->vbi.start[1] = cx->is_50hz ? 318 : 273;
+               cx->vbi.sliced_decoder_line_size = cx->is_60hz ? 272 : 284;
+               CX18_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)cx->std);
+
+               /* Tuner */
+               cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std);
+               break;
+       }
+
+       case VIDIOC_S_TUNER: {  /* Setting tuner can only set audio mode */
+               struct v4l2_tuner *vt = arg;
+
+               if (vt->index != 0)
+                       return -EINVAL;
+
+               cx18_call_i2c_clients(cx, VIDIOC_S_TUNER, vt);
+               break;
+       }
+
+       case VIDIOC_G_TUNER: {
+               struct v4l2_tuner *vt = arg;
+
+               if (vt->index != 0)
+                       return -EINVAL;
+
+               memset(vt, 0, sizeof(*vt));
+               cx18_call_i2c_clients(cx, VIDIOC_G_TUNER, vt);
+
+               if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
+                       strlcpy(vt->name, "cx18 Radio Tuner", sizeof(vt->name));
+                       vt->type = V4L2_TUNER_RADIO;
+               } else {
+                       strlcpy(vt->name, "cx18 TV Tuner", sizeof(vt->name));
+                       vt->type = V4L2_TUNER_ANALOG_TV;
+               }
+               break;
+       }
+
+       case VIDIOC_G_SLICED_VBI_CAP: {
+               struct v4l2_sliced_vbi_cap *cap = arg;
+               int set = cx->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
+               int f, l;
+               enum v4l2_buf_type type = cap->type;
+
+               memset(cap, 0, sizeof(*cap));
+               cap->type = type;
+               if (type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
+                       for (f = 0; f < 2; f++) {
+                               for (l = 0; l < 24; l++) {
+                                       if (valid_service_line(f, l, cx->is_50hz))
+                                               cap->service_lines[f][l] = set;
+                               }
+                       }
+                       return 0;
+               }
+               return -EINVAL;
+       }
+
+       case VIDIOC_ENCODER_CMD:
+       case VIDIOC_TRY_ENCODER_CMD: {
+               struct v4l2_encoder_cmd *enc = arg;
+               int try = cmd == VIDIOC_TRY_ENCODER_CMD;
+
+               memset(&enc->raw, 0, sizeof(enc->raw));
+               switch (enc->cmd) {
+               case V4L2_ENC_CMD_START:
+                       enc->flags = 0;
+                       if (try)
+                               return 0;
+                       return cx18_start_capture(id);
+
+               case V4L2_ENC_CMD_STOP:
+                       enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
+                       if (try)
+                               return 0;
+                       cx18_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
+                       return 0;
+
+               case V4L2_ENC_CMD_PAUSE:
+                       enc->flags = 0;
+                       if (try)
+                               return 0;
+                       if (!atomic_read(&cx->capturing))
+                               return -EPERM;
+                       if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
+                               return 0;
+                       cx18_mute(cx);
+                       cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, cx18_find_handle(cx));
+                       break;
+
+               case V4L2_ENC_CMD_RESUME:
+                       enc->flags = 0;
+                       if (try)
+                               return 0;
+                       if (!atomic_read(&cx->capturing))
+                               return -EPERM;
+                       if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
+                               return 0;
+                       cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, cx18_find_handle(cx));
+                       cx18_unmute(cx);
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       }
+
+       case VIDIOC_LOG_STATUS:
+       {
+               struct v4l2_input vidin;
+               struct v4l2_audio audin;
+               int i;
+
+               CX18_INFO("=================  START STATUS CARD #%d  =================\n", cx->num);
+               if (cx->hw_flags & CX18_HW_TVEEPROM) {
+                       struct tveeprom tv;
+
+                       cx18_read_eeprom(cx, &tv);
+               }
+               cx18_call_i2c_clients(cx, VIDIOC_LOG_STATUS, NULL);
+               cx18_get_input(cx, cx->active_input, &vidin);
+               cx18_get_audio_input(cx, cx->audio_input, &audin);
+               CX18_INFO("Video Input: %s\n", vidin.name);
+               CX18_INFO("Audio Input: %s\n", audin.name);
+               CX18_INFO("Tuner: %s\n",
+                       test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ?
+                       "Radio" : "TV");
+               cx2341x_log_status(&cx->params, cx->name);
+               CX18_INFO("Status flags: 0x%08lx\n", cx->i_flags);
+               for (i = 0; i < CX18_MAX_STREAMS; i++) {
+                       struct cx18_stream *s = &cx->streams[i];
+
+                       if (s->v4l2dev == NULL || s->buffers == 0)
+                               continue;
+                       CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n",
+                               s->name, s->s_flags,
+                               (s->buffers - s->q_free.buffers) * 100 / s->buffers,
+                               (s->buffers * s->buf_size) / 1024, s->buffers);
+               }
+               CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n",
+                               (long long)cx->mpg_data_received,
+                               (long long)cx->vbi_data_inserted);
+               CX18_INFO("==================  END STATUS CARD #%d  ==================\n", cx->num);
+               break;
+       }
+
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int cx18_v4l2_do_ioctl(struct inode *inode, struct file *filp,
+                             unsigned int cmd, void *arg)
+{
+       struct cx18_open_id *id = (struct cx18_open_id *)filp->private_data;
+       struct cx18 *cx = id->cx;
+       int ret;
+
+       /* check priority */
+       switch (cmd) {
+       case VIDIOC_S_CTRL:
+       case VIDIOC_S_STD:
+       case VIDIOC_S_INPUT:
+       case VIDIOC_S_TUNER:
+       case VIDIOC_S_FREQUENCY:
+       case VIDIOC_S_FMT:
+       case VIDIOC_S_CROP:
+       case VIDIOC_S_EXT_CTRLS:
+               ret = v4l2_prio_check(&cx->prio, &id->prio);
+               if (ret)
+                       return ret;
+       }
+
+       switch (cmd) {
+       case VIDIOC_DBG_G_REGISTER:
+       case VIDIOC_DBG_S_REGISTER:
+       case VIDIOC_G_CHIP_IDENT:
+       case VIDIOC_INT_S_AUDIO_ROUTING:
+       case VIDIOC_INT_RESET:
+               if (cx18_debug & CX18_DBGFLG_IOCTL) {
+                       printk(KERN_INFO "cx18%d ioctl: ", cx->num);
+                       v4l_printk_ioctl(cmd);
+               }
+               return cx18_debug_ioctls(filp, cmd, arg);
+
+       case VIDIOC_G_PRIORITY:
+       case VIDIOC_S_PRIORITY:
+       case VIDIOC_QUERYCAP:
+       case VIDIOC_ENUMINPUT:
+       case VIDIOC_G_INPUT:
+       case VIDIOC_S_INPUT:
+       case VIDIOC_G_FMT:
+       case VIDIOC_S_FMT:
+       case VIDIOC_TRY_FMT:
+       case VIDIOC_ENUM_FMT:
+       case VIDIOC_CROPCAP:
+       case VIDIOC_G_CROP:
+       case VIDIOC_S_CROP:
+       case VIDIOC_G_FREQUENCY:
+       case VIDIOC_S_FREQUENCY:
+       case VIDIOC_ENUMSTD:
+       case VIDIOC_G_STD:
+       case VIDIOC_S_STD:
+       case VIDIOC_S_TUNER:
+       case VIDIOC_G_TUNER:
+       case VIDIOC_ENUMAUDIO:
+       case VIDIOC_S_AUDIO:
+       case VIDIOC_G_AUDIO:
+       case VIDIOC_G_SLICED_VBI_CAP:
+       case VIDIOC_LOG_STATUS:
+       case VIDIOC_G_ENC_INDEX:
+       case VIDIOC_ENCODER_CMD:
+       case VIDIOC_TRY_ENCODER_CMD:
+               if (cx18_debug & CX18_DBGFLG_IOCTL) {
+                       printk(KERN_INFO "cx18%d ioctl: ", cx->num);
+                       v4l_printk_ioctl(cmd);
+               }
+               return cx18_v4l2_ioctls(cx, filp, cmd, arg);
+
+       case VIDIOC_QUERYMENU:
+       case VIDIOC_QUERYCTRL:
+       case VIDIOC_S_CTRL:
+       case VIDIOC_G_CTRL:
+       case VIDIOC_S_EXT_CTRLS:
+       case VIDIOC_G_EXT_CTRLS:
+       case VIDIOC_TRY_EXT_CTRLS:
+               if (cx18_debug & CX18_DBGFLG_IOCTL) {
+                       printk(KERN_INFO "cx18%d ioctl: ", cx->num);
+                       v4l_printk_ioctl(cmd);
+               }
+               return cx18_control_ioctls(cx, cmd, arg);
+
+       case 0x00005401:        /* Handle isatty() calls */
+               return -EINVAL;
+       default:
+               return v4l_compat_translate_ioctl(inode, filp, cmd, arg,
+                                                  cx18_v4l2_do_ioctl);
+       }
+       return 0;
+}
+
+int cx18_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+                   unsigned long arg)
+{
+       struct cx18_open_id *id = (struct cx18_open_id *)filp->private_data;
+       struct cx18 *cx = id->cx;
+       int res;
+
+       mutex_lock(&cx->serialize_lock);
+       res = video_usercopy(inode, filp, cmd, arg, cx18_v4l2_do_ioctl);
+       mutex_unlock(&cx->serialize_lock);
+       return res;
+}
diff --git a/drivers/media/video/cx18/cx18-ioctl.h b/drivers/media/video/cx18/cx18-ioctl.h
new file mode 100644 (file)
index 0000000..9f4c7eb
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  cx18 ioctl system call
+ *
+ *  Derived from ivtv-ioctl.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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
+ */
+
+u16 cx18_service2vbi(int type);
+void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal);
+u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt);
+int cx18_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+                   unsigned long arg);
+int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd,
+                    void *arg);
diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c
new file mode 100644 (file)
index 0000000..6e14f8b
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ *  cx18 interrupt handling
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 "cx18-driver.h"
+#include "cx18-firmware.h"
+#include "cx18-fileops.h"
+#include "cx18-queue.h"
+#include "cx18-irq.h"
+#include "cx18-ioctl.h"
+#include "cx18-mailbox.h"
+#include "cx18-vbi.h"
+#include "cx18-scb.h"
+
+#define DMA_MAGIC_COOKIE 0x000001fe
+
+static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb)
+{
+       u32 handle = mb->args[0];
+       struct cx18_stream *s = NULL;
+       struct cx18_buffer *buf;
+       u32 off;
+       int i;
+       int id;
+
+       for (i = 0; i < CX18_MAX_STREAMS; i++) {
+               s = &cx->streams[i];
+               if ((handle == s->handle) && (s->dvb.enabled))
+                       break;
+               if (s->v4l2dev && handle == s->handle)
+                       break;
+       }
+       if (i == CX18_MAX_STREAMS) {
+               CX18_WARN("DMA done for unknown handle %d for stream %s\n",
+                       handle, s->name);
+               mb->error = CXERR_NOT_OPEN;
+               mb->cmd = 0;
+               cx18_mb_ack(cx, mb);
+               return;
+       }
+
+       off = mb->args[1];
+       if (mb->args[2] != 1)
+               CX18_WARN("Ack struct = %d for %s\n",
+                       mb->args[2], s->name);
+       id = read_enc(off);
+       buf = cx18_queue_find_buf(s, id, read_enc(off + 4));
+       CX18_DEBUG_HI_DMA("DMA DONE for %s (buffer %d)\n", s->name, id);
+       if (buf) {
+               cx18_buf_sync_for_cpu(s, buf);
+               if (s->type == CX18_ENC_STREAM_TYPE_TS && s->dvb.enabled) {
+                       /* process the buffer here */
+                       CX18_DEBUG_HI_DMA("TS recv and sent bytesused=%d\n",
+                                       buf->bytesused);
+
+                       dvb_dmx_swfilter(&s->dvb.demux, buf->buf,
+                                       buf->bytesused);
+
+                       cx18_buf_sync_for_device(s, buf);
+                       cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
+                           (void *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem,
+                           1, buf->id, s->buf_size);
+               } else
+                       set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags);
+       } else {
+               CX18_WARN("Could not find buf %d for stream %s\n",
+                               read_enc(off), s->name);
+       }
+       mb->error = 0;
+       mb->cmd = 0;
+       cx18_mb_ack(cx, mb);
+       wake_up(&cx->dma_waitq);
+       if (s->id != -1)
+               wake_up(&s->waitq);
+}
+
+static void epu_debug(struct cx18 *cx, struct cx18_mailbox *mb)
+{
+       char str[256] = { 0 };
+       char *p;
+
+       if (mb->args[1]) {
+               setup_page(mb->args[1]);
+               memcpy_fromio(str, cx->enc_mem + mb->args[1], 252);
+               str[252] = 0;
+       }
+       cx18_mb_ack(cx, mb);
+       CX18_DEBUG_INFO("%x %s\n", mb->args[0], str);
+       p = strchr(str, '.');
+       if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags) && p && p > str)
+               CX18_INFO("FW version: %s\n", p - 1);
+}
+
+static void hpu_cmd(struct cx18 *cx, u32 sw1)
+{
+       struct cx18_mailbox mb;
+
+       if (sw1 & IRQ_CPU_TO_EPU) {
+               memcpy_fromio(&mb, &cx->scb->cpu2epu_mb, sizeof(mb));
+               mb.error = 0;
+
+               switch (mb.cmd) {
+               case CX18_EPU_DMA_DONE:
+                       epu_dma_done(cx, &mb);
+                       break;
+               case CX18_EPU_DEBUG:
+                       epu_debug(cx, &mb);
+                       break;
+               default:
+                       CX18_WARN("Unexpected mailbox command %08x\n", mb.cmd);
+                       break;
+               }
+       }
+       if (sw1 & (IRQ_APU_TO_EPU | IRQ_HPU_TO_EPU))
+               CX18_WARN("Unexpected interrupt %08x\n", sw1);
+}
+
+irqreturn_t cx18_irq_handler(int irq, void *dev_id)
+{
+       struct cx18 *cx = (struct cx18 *)dev_id;
+       u32 sw1, sw1_mask;
+       u32 sw2, sw2_mask;
+       u32 hw2, hw2_mask;
+
+       spin_lock(&cx->dma_reg_lock);
+
+       hw2_mask = read_reg(HW2_INT_MASK5_PCI);
+       hw2 = read_reg(HW2_INT_CLR_STATUS) & hw2_mask;
+       sw2_mask = read_reg(SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK;
+       sw2 = read_reg(SW2_INT_STATUS) & sw2_mask;
+       sw1_mask = read_reg(SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU;
+       sw1 = read_reg(SW1_INT_STATUS) & sw1_mask;
+
+       write_reg(sw2&sw2_mask, SW2_INT_STATUS);
+       write_reg(sw1&sw1_mask, SW1_INT_STATUS);
+       write_reg(hw2&hw2_mask, HW2_INT_CLR_STATUS);
+
+       if (sw1 || sw2 || hw2)
+               CX18_DEBUG_HI_IRQ("SW1: %x  SW2: %x  HW2: %x\n", sw1, sw2, hw2);
+
+       /* To do: interrupt-based I2C handling
+       if (hw2 & 0x00c00000) {
+       }
+       */
+
+       if (sw2) {
+               if (sw2 & (cx->scb->cpu2hpu_irq_ack | cx->scb->cpu2epu_irq_ack))
+                       wake_up(&cx->mb_cpu_waitq);
+               if (sw2 & (cx->scb->apu2hpu_irq_ack | cx->scb->apu2epu_irq_ack))
+                       wake_up(&cx->mb_apu_waitq);
+               if (sw2 & cx->scb->epu2hpu_irq_ack)
+                       wake_up(&cx->mb_epu_waitq);
+               if (sw2 & cx->scb->hpu2epu_irq_ack)
+                       wake_up(&cx->mb_hpu_waitq);
+       }
+
+       if (sw1)
+               hpu_cmd(cx, sw1);
+       spin_unlock(&cx->dma_reg_lock);
+
+       return (hw2 | sw1 | sw2) ? IRQ_HANDLED : IRQ_NONE;
+}
diff --git a/drivers/media/video/cx18/cx18-irq.h b/drivers/media/video/cx18/cx18-irq.h
new file mode 100644 (file)
index 0000000..379f704
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ *  cx18 interrupt handling
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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
+ */
+
+#define HW2_I2C1_INT                   (1 << 22)
+#define HW2_I2C2_INT                   (1 << 23)
+#define HW2_INT_CLR_STATUS             0xc730c4
+#define HW2_INT_MASK5_PCI              0xc730e4
+#define SW1_INT_SET                     0xc73100
+#define SW1_INT_STATUS                  0xc73104
+#define SW1_INT_ENABLE_PCI              0xc7311c
+#define SW2_INT_SET                     0xc73140
+#define SW2_INT_STATUS                  0xc73144
+#define SW2_INT_ENABLE_PCI              0xc7315c
+
+irqreturn_t cx18_irq_handler(int irq, void *dev_id);
+
+void cx18_irq_work_handler(struct work_struct *work);
+void cx18_dma_stream_dec_prepare(struct cx18_stream *s, u32 offset, int lock);
+void cx18_unfinished_dma(unsigned long arg);
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c
new file mode 100644 (file)
index 0000000..0c5f328
--- /dev/null
@@ -0,0 +1,372 @@
+/*
+ *  cx18 mailbox functions
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 <stdarg.h>
+
+#include "cx18-driver.h"
+#include "cx18-scb.h"
+#include "cx18-irq.h"
+#include "cx18-mailbox.h"
+
+#define API_FAST (1 << 2) /* Short timeout */
+#define API_SLOW (1 << 3) /* Additional 300ms timeout */
+
+#define APU 0
+#define CPU 1
+#define EPU 2
+#define HPU 3
+
+struct cx18_api_info {
+       u32 cmd;
+       u8 flags;               /* Flags, see above */
+       u8 rpu;                 /* Processing unit */
+       const char *name;       /* The name of the command */
+};
+
+#define API_ENTRY(rpu, x, f) { (x), (f), (rpu), #x }
+
+static const struct cx18_api_info api_info[] = {
+       /* MPEG encoder API */
+       API_ENTRY(CPU, CX18_CPU_SET_CHANNEL_TYPE,               0),
+       API_ENTRY(CPU, CX18_EPU_DEBUG,                          0),
+       API_ENTRY(CPU, CX18_CREATE_TASK,                        0),
+       API_ENTRY(CPU, CX18_DESTROY_TASK,                       0),
+       API_ENTRY(CPU, CX18_CPU_CAPTURE_START,                  API_SLOW),
+       API_ENTRY(CPU, CX18_CPU_CAPTURE_STOP,                   API_SLOW),
+       API_ENTRY(CPU, CX18_CPU_CAPTURE_PAUSE,                  0),
+       API_ENTRY(CPU, CX18_CPU_CAPTURE_RESUME,                 0),
+       API_ENTRY(CPU, CX18_CPU_SET_CHANNEL_TYPE,               0),
+       API_ENTRY(CPU, CX18_CPU_SET_STREAM_OUTPUT_TYPE,         0),
+       API_ENTRY(CPU, CX18_CPU_SET_VIDEO_IN,                   0),
+       API_ENTRY(CPU, CX18_CPU_SET_VIDEO_RATE,                 0),
+       API_ENTRY(CPU, CX18_CPU_SET_VIDEO_RESOLUTION,           0),
+       API_ENTRY(CPU, CX18_CPU_SET_FILTER_PARAM,               0),
+       API_ENTRY(CPU, CX18_CPU_SET_SPATIAL_FILTER_TYPE,        0),
+       API_ENTRY(CPU, CX18_CPU_SET_MEDIAN_CORING,              0),
+       API_ENTRY(CPU, CX18_CPU_SET_INDEXTABLE,                 0),
+       API_ENTRY(CPU, CX18_CPU_SET_AUDIO_PARAMETERS,           0),
+       API_ENTRY(CPU, CX18_CPU_SET_VIDEO_MUTE,                 0),
+       API_ENTRY(CPU, CX18_CPU_SET_AUDIO_MUTE,                 0),
+       API_ENTRY(CPU, CX18_CPU_SET_MISC_PARAMETERS,            0),
+       API_ENTRY(CPU, CX18_CPU_SET_RAW_VBI_PARAM,              API_SLOW),
+       API_ENTRY(CPU, CX18_CPU_SET_CAPTURE_LINE_NO,            0),
+       API_ENTRY(CPU, CX18_CPU_SET_COPYRIGHT,                  0),
+       API_ENTRY(CPU, CX18_CPU_SET_AUDIO_PID,                  0),
+       API_ENTRY(CPU, CX18_CPU_SET_VIDEO_PID,                  0),
+       API_ENTRY(CPU, CX18_CPU_SET_VER_CROP_LINE,              0),
+       API_ENTRY(CPU, CX18_CPU_SET_GOP_STRUCTURE,              0),
+       API_ENTRY(CPU, CX18_CPU_SET_SCENE_CHANGE_DETECTION,     0),
+       API_ENTRY(CPU, CX18_CPU_SET_ASPECT_RATIO,               0),
+       API_ENTRY(CPU, CX18_CPU_SET_SKIP_INPUT_FRAME,           0),
+       API_ENTRY(CPU, CX18_CPU_SET_SLICED_VBI_PARAM,           0),
+       API_ENTRY(CPU, CX18_CPU_SET_USERDATA_PLACE_HOLDER,      0),
+       API_ENTRY(CPU, CX18_CPU_GET_ENC_PTS,                    0),
+       API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK,                 0),
+       API_ENTRY(CPU, CX18_CPU_DE_SET_MDL,                     API_FAST),
+       API_ENTRY(0, 0,                                         0),
+};
+
+static const struct cx18_api_info *find_api_info(u32 cmd)
+{
+       int i;
+
+       for (i = 0; api_info[i].cmd; i++)
+               if (api_info[i].cmd == cmd)
+                       return &api_info[i];
+       return NULL;
+}
+
+static struct cx18_mailbox *cx18_mb_is_complete(struct cx18 *cx, int rpu,
+               u32 *state, u32 *irq, u32 *req)
+{
+       struct cx18_mailbox *mb = NULL;
+       int wait_count = 0;
+       u32 ack;
+
+       switch (rpu) {
+       case APU:
+               mb = &cx->scb->epu2apu_mb;
+               *state = readl(&cx->scb->apu_state);
+               *irq = readl(&cx->scb->epu2apu_irq);
+               break;
+
+       case CPU:
+               mb = &cx->scb->epu2cpu_mb;
+               *state = readl(&cx->scb->cpu_state);
+               *irq = readl(&cx->scb->epu2cpu_irq);
+               break;
+
+       case HPU:
+               mb = &cx->scb->epu2hpu_mb;
+               *state = readl(&cx->scb->hpu_state);
+               *irq = readl(&cx->scb->epu2hpu_irq);
+               break;
+       }
+
+       if (mb == NULL)
+               return mb;
+
+       do {
+               *req = readl(&mb->request);
+               ack = readl(&mb->ack);
+               wait_count++;
+       } while (*req != ack && wait_count < 600);
+
+       if (*req == ack) {
+               (*req)++;
+               if (*req == 0 || *req == 0xffffffff)
+                       *req = 1;
+               return mb;
+       }
+       return NULL;
+}
+
+long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb)
+{
+       const struct cx18_api_info *info = find_api_info(mb->cmd);
+       struct cx18_mailbox *ack_mb;
+       u32 ack_irq;
+       u8 rpu = CPU;
+
+       if (info == NULL && mb->cmd) {
+               CX18_WARN("Cannot ack unknown command %x\n", mb->cmd);
+               return -EINVAL;
+       }
+       if (info)
+               rpu = info->rpu;
+
+       switch (rpu) {
+       case HPU:
+               ack_irq = IRQ_EPU_TO_HPU_ACK;
+               ack_mb = &cx->scb->hpu2epu_mb;
+               break;
+       case APU:
+               ack_irq = IRQ_EPU_TO_APU_ACK;
+               ack_mb = &cx->scb->apu2epu_mb;
+               break;
+       case CPU:
+               ack_irq = IRQ_EPU_TO_CPU_ACK;
+               ack_mb = &cx->scb->cpu2epu_mb;
+               break;
+       default:
+               CX18_WARN("Unknown RPU for command %x\n", mb->cmd);
+               return -EINVAL;
+       }
+
+       setup_page(SCB_OFFSET);
+       write_sync(mb->request, &ack_mb->ack);
+       write_reg(ack_irq, SW2_INT_SET);
+       return 0;
+}
+
+
+static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
+{
+       const struct cx18_api_info *info = find_api_info(cmd);
+       u32 state = 0, irq = 0, req, oldreq, err;
+       struct cx18_mailbox *mb;
+       wait_queue_head_t *waitq;
+       int timeout = 100;
+       int cnt = 0;
+       int sig = 0;
+       int i;
+
+       if (info == NULL) {
+               CX18_WARN("unknown cmd %x\n", cmd);
+               return -EINVAL;
+       }
+
+       if (cmd == CX18_CPU_DE_SET_MDL)
+               CX18_DEBUG_HI_API("%s\n", info->name);
+       else
+               CX18_DEBUG_API("%s\n", info->name);
+       setup_page(SCB_OFFSET);
+       mb = cx18_mb_is_complete(cx, info->rpu, &state, &irq, &req);
+
+       if (mb == NULL) {
+               CX18_ERR("mb %s busy\n", info->name);
+               return -EBUSY;
+       }
+
+       oldreq = req - 1;
+       writel(cmd, &mb->cmd);
+       for (i = 0; i < args; i++)
+               writel(data[i], &mb->args[i]);
+       writel(0, &mb->error);
+       writel(req, &mb->request);
+
+       switch (info->rpu) {
+       case APU: waitq = &cx->mb_apu_waitq; break;
+       case CPU: waitq = &cx->mb_cpu_waitq; break;
+       case EPU: waitq = &cx->mb_epu_waitq; break;
+       case HPU: waitq = &cx->mb_hpu_waitq; break;
+       default: return -EINVAL;
+       }
+       if (info->flags & API_FAST)
+               timeout /= 2;
+       write_reg(irq, SW1_INT_SET);
+
+       while (!sig && readl(&mb->ack) != readl(&mb->request) && cnt < 660) {
+               if (cnt > 200 && !in_atomic())
+                       sig = cx18_msleep_timeout(10, 1);
+               cnt++;
+       }
+       if (sig)
+               return -EINTR;
+       if (cnt == 660) {
+               writel(oldreq, &mb->request);
+               CX18_ERR("mb %s failed\n", info->name);
+               return -EINVAL;
+       }
+       for (i = 0; i < MAX_MB_ARGUMENTS; i++)
+               data[i] = readl(&mb->args[i]);
+       err = readl(&mb->error);
+       if (!in_atomic() && (info->flags & API_SLOW))
+               cx18_msleep_timeout(300, 0);
+       if (err)
+               CX18_DEBUG_API("mailbox error %08x for command %s\n", err,
+                               info->name);
+       return err ? -EIO : 0;
+}
+
+int cx18_api(struct cx18 *cx, u32 cmd, int args, u32 data[])
+{
+       int res = cx18_api_call(cx, cmd, args, data);
+
+       /* Allow a single retry, probably already too late though.
+          If there is no free mailbox then that is usually an indication
+          of a more serious problem. */
+       return (res == -EBUSY) ? cx18_api_call(cx, cmd, args, data) : res;
+}
+
+static int cx18_set_filter_param(struct cx18_stream *s)
+{
+       struct cx18 *cx = s->cx;
+       u32 mode;
+       int ret;
+
+       mode = (cx->filter_mode & 1) ? 2 : (cx->spatial_strength ? 1 : 0);
+       ret = cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
+                       s->handle, 1, mode, cx->spatial_strength);
+       mode = (cx->filter_mode & 2) ? 2 : (cx->temporal_strength ? 1 : 0);
+       ret = ret ? ret : cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
+                       s->handle, 0, mode, cx->temporal_strength);
+       ret = ret ? ret : cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
+                       s->handle, 2, cx->filter_mode >> 2, 0);
+       return ret;
+}
+
+int cx18_api_func(void *priv, u32 cmd, int in, int out,
+               u32 data[CX2341X_MBOX_MAX_DATA])
+{
+       struct cx18 *cx = priv;
+       struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_MPG];
+
+       switch (cmd) {
+       case CX2341X_ENC_SET_OUTPUT_PORT:
+               return 0;
+       case CX2341X_ENC_SET_FRAME_RATE:
+               return cx18_vapi(cx, CX18_CPU_SET_VIDEO_IN, 6,
+                               s->handle, 0, 0, 0, 0, data[0]);
+       case CX2341X_ENC_SET_FRAME_SIZE:
+               return cx18_vapi(cx, CX18_CPU_SET_VIDEO_RESOLUTION, 3,
+                               s->handle, data[1], data[0]);
+       case CX2341X_ENC_SET_STREAM_TYPE:
+               return cx18_vapi(cx, CX18_CPU_SET_STREAM_OUTPUT_TYPE, 2,
+                               s->handle, data[0]);
+       case CX2341X_ENC_SET_ASPECT_RATIO:
+               return cx18_vapi(cx, CX18_CPU_SET_ASPECT_RATIO, 2,
+                               s->handle, data[0]);
+
+       case CX2341X_ENC_SET_GOP_PROPERTIES:
+               return cx18_vapi(cx, CX18_CPU_SET_GOP_STRUCTURE, 3,
+                               s->handle, data[0], data[1]);
+       case CX2341X_ENC_SET_GOP_CLOSURE:
+               return 0;
+       case CX2341X_ENC_SET_AUDIO_PROPERTIES:
+               return cx18_vapi(cx, CX18_CPU_SET_AUDIO_PARAMETERS, 2,
+                               s->handle, data[0]);
+       case CX2341X_ENC_MUTE_AUDIO:
+               return cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
+                               s->handle, data[0]);
+       case CX2341X_ENC_SET_BIT_RATE:
+               return cx18_vapi(cx, CX18_CPU_SET_VIDEO_RATE, 5,
+                               s->handle, data[0], data[1], data[2], data[3]);
+       case CX2341X_ENC_MUTE_VIDEO:
+               return cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2,
+                               s->handle, data[0]);
+       case CX2341X_ENC_SET_FRAME_DROP_RATE:
+               return cx18_vapi(cx, CX18_CPU_SET_SKIP_INPUT_FRAME, 2,
+                               s->handle, data[0]);
+       case CX2341X_ENC_MISC:
+               return cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 4,
+                               s->handle, data[0], data[1], data[2]);
+       case CX2341X_ENC_SET_DNR_FILTER_MODE:
+               cx->filter_mode = (data[0] & 3) | (data[1] << 2);
+               return cx18_set_filter_param(s);
+       case CX2341X_ENC_SET_DNR_FILTER_PROPS:
+               cx->spatial_strength = data[0];
+               cx->temporal_strength = data[1];
+               return cx18_set_filter_param(s);
+       case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:
+               return cx18_vapi(cx, CX18_CPU_SET_SPATIAL_FILTER_TYPE, 3,
+                               s->handle, data[0], data[1]);
+       case CX2341X_ENC_SET_CORING_LEVELS:
+               return cx18_vapi(cx, CX18_CPU_SET_MEDIAN_CORING, 5,
+                               s->handle, data[0], data[1], data[2], data[3]);
+       }
+       CX18_WARN("Unknown cmd %x\n", cmd);
+       return 0;
+}
+
+int cx18_vapi_result(struct cx18 *cx, u32 data[MAX_MB_ARGUMENTS],
+               u32 cmd, int args, ...)
+{
+       va_list ap;
+       int i;
+
+       va_start(ap, args);
+       for (i = 0; i < args; i++)
+               data[i] = va_arg(ap, u32);
+       va_end(ap);
+       return cx18_api(cx, cmd, args, data);
+}
+
+int cx18_vapi(struct cx18 *cx, u32 cmd, int args, ...)
+{
+       u32 data[MAX_MB_ARGUMENTS];
+       va_list ap;
+       int i;
+
+       if (cx == NULL) {
+               CX18_ERR("cx == NULL (cmd=%x)\n", cmd);
+               return 0;
+       }
+       if (args > MAX_MB_ARGUMENTS) {
+               CX18_ERR("args too big (cmd=%x)\n", cmd);
+               args = MAX_MB_ARGUMENTS;
+       }
+       va_start(ap, args);
+       for (i = 0; i < args; i++)
+               data[i] = va_arg(ap, u32);
+       va_end(ap);
+       return cx18_api(cx, cmd, args, data);
+}
diff --git a/drivers/media/video/cx18/cx18-mailbox.h b/drivers/media/video/cx18/cx18-mailbox.h
new file mode 100644 (file)
index 0000000..d995641
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ *  cx18 mailbox functions
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 _CX18_MAILBOX_H_
+#define _CX18_MAILBOX_H_
+
+/* mailbox max args */
+#define MAX_MB_ARGUMENTS 6
+/* compatibility, should be same as the define in cx2341x.h */
+#define CX2341X_MBOX_MAX_DATA 16
+
+#define MB_RESERVED_HANDLE_0 0
+#define MB_RESERVED_HANDLE_1 0xFFFFFFFF
+
+struct cx18;
+
+/* The cx18_mailbox struct is the mailbox structure which is used for passing
+   messages between processors */
+struct cx18_mailbox {
+    /* The sender sets a handle in 'request' after he fills the command. The
+       'request' should be different than 'ack'. The sender, also, generates
+       an interrupt on XPU2YPU_irq where XPU is the sender and YPU is the
+       receiver. */
+    u32       request;
+    /* The receiver detects a new command when 'req' is different than 'ack'.
+       He sets 'ack' to the same value as 'req' to clear the command. He, also,
+       generates an interrupt on YPU2XPU_irq where XPU is the sender and YPU
+       is the receiver. */
+    u32       ack;
+    u32       reserved[6];
+    /* 'cmd' identifies the command. The list of these commands are in
+       cx23418.h */
+    u32       cmd;
+    /* Each command can have up to 6 arguments */
+    u32       args[MAX_MB_ARGUMENTS];
+    /* The return code can be one of the codes in the file cx23418.h. If the
+       command is completed successfuly, the error will be ERR_SYS_SUCCESS.
+       If it is pending, the code is ERR_SYS_PENDING. If it failed, the error
+       code would indicate the task from which the error originated and will
+       be one of the errors in cx23418.h. In that case, the following
+       applies ((error & 0xff) != 0).
+       If the command is pending, the return will be passed in a MB from the
+       receiver to the sender. 'req' will be returned in args[0] */
+    u32       error;
+};
+
+int cx18_api(struct cx18 *cx, u32 cmd, int args, u32 data[]);
+int cx18_vapi_result(struct cx18 *cx, u32 data[MAX_MB_ARGUMENTS], u32 cmd,
+               int args, ...);
+int cx18_vapi(struct cx18 *cx, u32 cmd, int args, ...);
+int cx18_api_func(void *priv, u32 cmd, int in, int out,
+               u32 data[CX2341X_MBOX_MAX_DATA]);
+long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb);
+
+#endif
diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c
new file mode 100644 (file)
index 0000000..65af1bb
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ *  cx18 buffer queues
+ *
+ *  Derived from ivtv-queue.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 "cx18-driver.h"
+#include "cx18-streams.h"
+#include "cx18-queue.h"
+#include "cx18-scb.h"
+
+int cx18_buf_copy_from_user(struct cx18_stream *s, struct cx18_buffer *buf,
+               const char __user *src, int copybytes)
+{
+       if (s->buf_size - buf->bytesused < copybytes)
+               copybytes = s->buf_size - buf->bytesused;
+       if (copy_from_user(buf->buf + buf->bytesused, src, copybytes))
+               return -EFAULT;
+       buf->bytesused += copybytes;
+       return copybytes;
+}
+
+void cx18_buf_swap(struct cx18_buffer *buf)
+{
+       int i;
+
+       for (i = 0; i < buf->bytesused; i += 4)
+               swab32s((u32 *)(buf->buf + i));
+}
+
+void cx18_queue_init(struct cx18_queue *q)
+{
+       INIT_LIST_HEAD(&q->list);
+       q->buffers = 0;
+       q->length = 0;
+       q->bytesused = 0;
+}
+
+void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf,
+               struct cx18_queue *q)
+{
+       unsigned long flags = 0;
+
+       /* clear the buffer if it is going to be enqueued to the free queue */
+       if (q == &s->q_free) {
+               buf->bytesused = 0;
+               buf->readpos = 0;
+               buf->b_flags = 0;
+       }
+       spin_lock_irqsave(&s->qlock, flags);
+       list_add_tail(&buf->list, &q->list);
+       q->buffers++;
+       q->length += s->buf_size;
+       q->bytesused += buf->bytesused - buf->readpos;
+       spin_unlock_irqrestore(&s->qlock, flags);
+}
+
+struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q)
+{
+       struct cx18_buffer *buf = NULL;
+       unsigned long flags = 0;
+
+       spin_lock_irqsave(&s->qlock, flags);
+       if (!list_empty(&q->list)) {
+               buf = list_entry(q->list.next, struct cx18_buffer, list);
+               list_del_init(q->list.next);
+               q->buffers--;
+               q->length -= s->buf_size;
+               q->bytesused -= buf->bytesused - buf->readpos;
+       }
+       spin_unlock_irqrestore(&s->qlock, flags);
+       return buf;
+}
+
+struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id,
+       u32 bytesused)
+{
+       struct cx18 *cx = s->cx;
+       struct list_head *p;
+
+       list_for_each(p, &s->q_free.list) {
+               struct cx18_buffer *buf =
+                       list_entry(p, struct cx18_buffer, list);
+
+               if (buf->id != id)
+                       continue;
+               buf->bytesused = bytesused;
+               /* the transport buffers are handled differently,
+                  so there is no need to move them to the full queue */
+               if (s->type == CX18_ENC_STREAM_TYPE_TS)
+                       return buf;
+               s->q_free.buffers--;
+               s->q_free.length -= s->buf_size;
+               s->q_full.buffers++;
+               s->q_full.length += s->buf_size;
+               s->q_full.bytesused += buf->bytesused;
+               list_move_tail(&buf->list, &s->q_full.list);
+               return buf;
+       }
+       CX18_ERR("Cannot find buffer %d for stream %s\n", id, s->name);
+       return NULL;
+}
+
+static void cx18_queue_move_buf(struct cx18_stream *s, struct cx18_queue *from,
+               struct cx18_queue *to, int clear, int full)
+{
+       struct cx18_buffer *buf =
+               list_entry(from->list.next, struct cx18_buffer, list);
+
+       list_move_tail(from->list.next, &to->list);
+       from->buffers--;
+       from->length -= s->buf_size;
+       from->bytesused -= buf->bytesused - buf->readpos;
+       /* special handling for q_free */
+       if (clear)
+               buf->bytesused = buf->readpos = buf->b_flags = 0;
+       else if (full) {
+               /* special handling for stolen buffers, assume
+                  all bytes are used. */
+               buf->bytesused = s->buf_size;
+               buf->readpos = buf->b_flags = 0;
+       }
+       to->buffers++;
+       to->length += s->buf_size;
+       to->bytesused += buf->bytesused - buf->readpos;
+}
+
+/* Move 'needed_bytes' worth of buffers from queue 'from' into queue 'to'.
+   If 'needed_bytes' == 0, then move all buffers from 'from' into 'to'.
+   If 'steal' != NULL, then buffers may also taken from that queue if
+   needed.
+
+   The buffer is automatically cleared if it goes to the free queue. It is
+   also cleared if buffers need to be taken from the 'steal' queue and
+   the 'from' queue is the free queue.
+
+   When 'from' is q_free, then needed_bytes is compared to the total
+   available buffer length, otherwise needed_bytes is compared to the
+   bytesused value. For the 'steal' queue the total available buffer
+   length is always used.
+
+   -ENOMEM is returned if the buffers could not be obtained, 0 if all
+   buffers where obtained from the 'from' list and if non-zero then
+   the number of stolen buffers is returned. */
+int cx18_queue_move(struct cx18_stream *s, struct cx18_queue *from,
+       struct cx18_queue *steal, struct cx18_queue *to, int needed_bytes)
+{
+       unsigned long flags;
+       int rc = 0;
+       int from_free = from == &s->q_free;
+       int to_free = to == &s->q_free;
+       int bytes_available;
+
+       spin_lock_irqsave(&s->qlock, flags);
+       if (needed_bytes == 0) {
+               from_free = 1;
+               needed_bytes = from->length;
+       }
+
+       bytes_available = from_free ? from->length : from->bytesused;
+       bytes_available += steal ? steal->length : 0;
+
+       if (bytes_available < needed_bytes) {
+               spin_unlock_irqrestore(&s->qlock, flags);
+               return -ENOMEM;
+       }
+       if (from_free) {
+               u32 old_length = to->length;
+
+               while (to->length - old_length < needed_bytes) {
+                       if (list_empty(&from->list))
+                               from = steal;
+                       if (from == steal)
+                               rc++;   /* keep track of 'stolen' buffers */
+                       cx18_queue_move_buf(s, from, to, 1, 0);
+               }
+       } else {
+               u32 old_bytesused = to->bytesused;
+
+               while (to->bytesused - old_bytesused < needed_bytes) {
+                       if (list_empty(&from->list))
+                               from = steal;
+                       if (from == steal)
+                               rc++;   /* keep track of 'stolen' buffers */
+                       cx18_queue_move_buf(s, from, to, to_free, rc);
+               }
+       }
+       spin_unlock_irqrestore(&s->qlock, flags);
+       return rc;
+}
+
+void cx18_flush_queues(struct cx18_stream *s)
+{
+       cx18_queue_move(s, &s->q_io, NULL, &s->q_free, 0);
+       cx18_queue_move(s, &s->q_full, NULL, &s->q_free, 0);
+}
+
+int cx18_stream_alloc(struct cx18_stream *s)
+{
+       struct cx18 *cx = s->cx;
+       int i;
+
+       if (s->buffers == 0)
+               return 0;
+
+       CX18_DEBUG_INFO("Allocate %s stream: %d x %d buffers (%dkB total)\n",
+               s->name, s->buffers, s->buf_size,
+               s->buffers * s->buf_size / 1024);
+
+       if (((char *)&cx->scb->cpu_mdl[cx->mdl_offset + s->buffers] -
+                               (char *)cx->scb) > SCB_RESERVED_SIZE) {
+               unsigned bufsz = (((char *)cx->scb) + SCB_RESERVED_SIZE -
+                                       ((char *)cx->scb->cpu_mdl));
+
+               CX18_ERR("Too many buffers, cannot fit in SCB area\n");
+               CX18_ERR("Max buffers = %zd\n",
+                       bufsz / sizeof(struct cx18_mdl));
+               return -ENOMEM;
+       }
+
+       s->mdl_offset = cx->mdl_offset;
+
+       /* allocate stream buffers. Initially all buffers are in q_free. */
+       for (i = 0; i < s->buffers; i++) {
+               struct cx18_buffer *buf =
+                       kzalloc(sizeof(struct cx18_buffer), GFP_KERNEL);
+
+               if (buf == NULL)
+                       break;
+               buf->buf = kmalloc(s->buf_size, GFP_KERNEL);
+               if (buf->buf == NULL) {
+                       kfree(buf);
+                       break;
+               }
+               buf->id = cx->buffer_id++;
+               INIT_LIST_HEAD(&buf->list);
+               buf->dma_handle = pci_map_single(s->cx->dev,
+                               buf->buf, s->buf_size, s->dma);
+               cx18_buf_sync_for_cpu(s, buf);
+               cx18_enqueue(s, buf, &s->q_free);
+       }
+       if (i == s->buffers) {
+               cx->mdl_offset += s->buffers;
+               return 0;
+       }
+       CX18_ERR("Couldn't allocate buffers for %s stream\n", s->name);
+       cx18_stream_free(s);
+       return -ENOMEM;
+}
+
+void cx18_stream_free(struct cx18_stream *s)
+{
+       struct cx18_buffer *buf;
+
+       /* move all buffers to q_free */
+       cx18_flush_queues(s);
+
+       /* empty q_free */
+       while ((buf = cx18_dequeue(s, &s->q_free))) {
+               pci_unmap_single(s->cx->dev, buf->dma_handle,
+                               s->buf_size, s->dma);
+               kfree(buf->buf);
+               kfree(buf);
+       }
+}
diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/video/cx18/cx18-queue.h
new file mode 100644 (file)
index 0000000..f86c8a6
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *  cx18 buffer queues
+ *
+ *  Derived from ivtv-queue.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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
+ */
+
+#define CX18_DMA_UNMAPPED      ((u32) -1)
+
+/* cx18_buffer utility functions */
+
+static inline void cx18_buf_sync_for_cpu(struct cx18_stream *s,
+       struct cx18_buffer *buf)
+{
+       pci_dma_sync_single_for_cpu(s->cx->dev, buf->dma_handle,
+                               s->buf_size, s->dma);
+}
+
+static inline void cx18_buf_sync_for_device(struct cx18_stream *s,
+       struct cx18_buffer *buf)
+{
+       pci_dma_sync_single_for_device(s->cx->dev, buf->dma_handle,
+                               s->buf_size, s->dma);
+}
+
+int cx18_buf_copy_from_user(struct cx18_stream *s, struct cx18_buffer *buf,
+       const char __user *src, int copybytes);
+void cx18_buf_swap(struct cx18_buffer *buf);
+
+/* cx18_queue utility functions */
+void cx18_queue_init(struct cx18_queue *q);
+void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf,
+       struct cx18_queue *q);
+struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q);
+int cx18_queue_move(struct cx18_stream *s, struct cx18_queue *from,
+       struct cx18_queue *steal, struct cx18_queue *to, int needed_bytes);
+struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id,
+       u32 bytesused);
+void cx18_flush_queues(struct cx18_stream *s);
+
+/* cx18_stream utility functions */
+int cx18_stream_alloc(struct cx18_stream *s);
+void cx18_stream_free(struct cx18_stream *s);
diff --git a/drivers/media/video/cx18/cx18-scb.c b/drivers/media/video/cx18/cx18-scb.c
new file mode 100644 (file)
index 0000000..30bc803
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ *  cx18 System Control Block initialization
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 "cx18-driver.h"
+#include "cx18-scb.h"
+
+void cx18_init_scb(struct cx18 *cx)
+{
+       setup_page(SCB_OFFSET);
+       memset_io(cx->scb, 0, 0x10000);
+
+       writel(IRQ_APU_TO_CPU,     &cx->scb->apu2cpu_irq);
+       writel(IRQ_CPU_TO_APU_ACK, &cx->scb->cpu2apu_irq_ack);
+       writel(IRQ_HPU_TO_CPU,     &cx->scb->hpu2cpu_irq);
+       writel(IRQ_CPU_TO_HPU_ACK, &cx->scb->cpu2hpu_irq_ack);
+       writel(IRQ_PPU_TO_CPU,     &cx->scb->ppu2cpu_irq);
+       writel(IRQ_CPU_TO_PPU_ACK, &cx->scb->cpu2ppu_irq_ack);
+       writel(IRQ_EPU_TO_CPU,     &cx->scb->epu2cpu_irq);
+       writel(IRQ_CPU_TO_EPU_ACK, &cx->scb->cpu2epu_irq_ack);
+
+       writel(IRQ_CPU_TO_APU,     &cx->scb->cpu2apu_irq);
+       writel(IRQ_APU_TO_CPU_ACK, &cx->scb->apu2cpu_irq_ack);
+       writel(IRQ_HPU_TO_APU,     &cx->scb->hpu2apu_irq);
+       writel(IRQ_APU_TO_HPU_ACK, &cx->scb->apu2hpu_irq_ack);
+       writel(IRQ_PPU_TO_APU,     &cx->scb->ppu2apu_irq);
+       writel(IRQ_APU_TO_PPU_ACK, &cx->scb->apu2ppu_irq_ack);
+       writel(IRQ_EPU_TO_APU,     &cx->scb->epu2apu_irq);
+       writel(IRQ_APU_TO_EPU_ACK, &cx->scb->apu2epu_irq_ack);
+
+       writel(IRQ_CPU_TO_HPU,     &cx->scb->cpu2hpu_irq);
+       writel(IRQ_HPU_TO_CPU_ACK, &cx->scb->hpu2cpu_irq_ack);
+       writel(IRQ_APU_TO_HPU,     &cx->scb->apu2hpu_irq);
+       writel(IRQ_HPU_TO_APU_ACK, &cx->scb->hpu2apu_irq_ack);
+       writel(IRQ_PPU_TO_HPU,     &cx->scb->ppu2hpu_irq);
+       writel(IRQ_HPU_TO_PPU_ACK, &cx->scb->hpu2ppu_irq_ack);
+       writel(IRQ_EPU_TO_HPU,     &cx->scb->epu2hpu_irq);
+       writel(IRQ_HPU_TO_EPU_ACK, &cx->scb->hpu2epu_irq_ack);
+
+       writel(IRQ_CPU_TO_PPU,     &cx->scb->cpu2ppu_irq);
+       writel(IRQ_PPU_TO_CPU_ACK, &cx->scb->ppu2cpu_irq_ack);
+       writel(IRQ_APU_TO_PPU,     &cx->scb->apu2ppu_irq);
+       writel(IRQ_PPU_TO_APU_ACK, &cx->scb->ppu2apu_irq_ack);
+       writel(IRQ_HPU_TO_PPU,     &cx->scb->hpu2ppu_irq);
+       writel(IRQ_PPU_TO_HPU_ACK, &cx->scb->ppu2hpu_irq_ack);
+       writel(IRQ_EPU_TO_PPU,     &cx->scb->epu2ppu_irq);
+       writel(IRQ_PPU_TO_EPU_ACK, &cx->scb->ppu2epu_irq_ack);
+
+       writel(IRQ_CPU_TO_EPU,     &cx->scb->cpu2epu_irq);
+       writel(IRQ_EPU_TO_CPU_ACK, &cx->scb->epu2cpu_irq_ack);
+       writel(IRQ_APU_TO_EPU,     &cx->scb->apu2epu_irq);
+       writel(IRQ_EPU_TO_APU_ACK, &cx->scb->epu2apu_irq_ack);
+       writel(IRQ_HPU_TO_EPU,     &cx->scb->hpu2epu_irq);
+       writel(IRQ_EPU_TO_HPU_ACK, &cx->scb->epu2hpu_irq_ack);
+       writel(IRQ_PPU_TO_EPU,     &cx->scb->ppu2epu_irq);
+       writel(IRQ_EPU_TO_PPU_ACK, &cx->scb->epu2ppu_irq_ack);
+
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2cpu_mb),
+                       &cx->scb->apu2cpu_mb_offset);
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2cpu_mb),
+                       &cx->scb->hpu2cpu_mb_offset);
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2cpu_mb),
+                       &cx->scb->ppu2cpu_mb_offset);
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2cpu_mb),
+                       &cx->scb->epu2cpu_mb_offset);
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2apu_mb),
+                       &cx->scb->cpu2apu_mb_offset);
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2apu_mb),
+                       &cx->scb->hpu2apu_mb_offset);
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2apu_mb),
+                       &cx->scb->ppu2apu_mb_offset);
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2apu_mb),
+                       &cx->scb->epu2apu_mb_offset);
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2hpu_mb),
+                       &cx->scb->cpu2hpu_mb_offset);
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2hpu_mb),
+                       &cx->scb->apu2hpu_mb_offset);
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2hpu_mb),
+                       &cx->scb->ppu2hpu_mb_offset);
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2hpu_mb),
+                       &cx->scb->epu2hpu_mb_offset);
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2ppu_mb),
+                       &cx->scb->cpu2ppu_mb_offset);
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2ppu_mb),
+                       &cx->scb->apu2ppu_mb_offset);
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2ppu_mb),
+                       &cx->scb->hpu2ppu_mb_offset);
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, epu2ppu_mb),
+                       &cx->scb->epu2ppu_mb_offset);
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu2epu_mb),
+                       &cx->scb->cpu2epu_mb_offset);
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, apu2epu_mb),
+                       &cx->scb->apu2epu_mb_offset);
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, hpu2epu_mb),
+                       &cx->scb->hpu2epu_mb_offset);
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, ppu2epu_mb),
+                       &cx->scb->ppu2epu_mb_offset);
+
+       writel(SCB_OFFSET + offsetof(struct cx18_scb, cpu_state),
+                       &cx->scb->ipc_offset);
+
+       writel(1, &cx->scb->hpu_state);
+       writel(1, &cx->scb->epu_state);
+}
diff --git a/drivers/media/video/cx18/cx18-scb.h b/drivers/media/video/cx18/cx18-scb.h
new file mode 100644 (file)
index 0000000..86b4cb1
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+ *  cx18 System Control Block initialization
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 CX18_SCB_H
+#define CX18_SCB_H
+
+#include "cx18-mailbox.h"
+
+/* NOTE: All ACK interrupts are in the SW2 register.  All non-ACK interrupts
+   are in the SW1 register. */
+
+#define IRQ_APU_TO_CPU         0x00000001
+#define IRQ_CPU_TO_APU_ACK     0x00000001
+#define IRQ_HPU_TO_CPU         0x00000002
+#define IRQ_CPU_TO_HPU_ACK     0x00000002
+#define IRQ_PPU_TO_CPU         0x00000004
+#define IRQ_CPU_TO_PPU_ACK     0x00000004
+#define IRQ_EPU_TO_CPU         0x00000008
+#define IRQ_CPU_TO_EPU_ACK     0x00000008
+
+#define IRQ_CPU_TO_APU         0x00000010
+#define IRQ_APU_TO_CPU_ACK     0x00000010
+#define IRQ_HPU_TO_APU         0x00000020
+#define IRQ_APU_TO_HPU_ACK     0x00000020
+#define IRQ_PPU_TO_APU         0x00000040
+#define IRQ_APU_TO_PPU_ACK     0x00000040
+#define IRQ_EPU_TO_APU         0x00000080
+#define IRQ_APU_TO_EPU_ACK     0x00000080
+
+#define IRQ_CPU_TO_HPU         0x00000100
+#define IRQ_HPU_TO_CPU_ACK     0x00000100
+#define IRQ_APU_TO_HPU         0x00000200
+#define IRQ_HPU_TO_APU_ACK     0x00000200
+#define IRQ_PPU_TO_HPU         0x00000400
+#define IRQ_HPU_TO_PPU_ACK     0x00000400
+#define IRQ_EPU_TO_HPU         0x00000800
+#define IRQ_HPU_TO_EPU_ACK     0x00000800
+
+#define IRQ_CPU_TO_PPU         0x00001000
+#define IRQ_PPU_TO_CPU_ACK     0x00001000
+#define IRQ_APU_TO_PPU         0x00002000
+#define IRQ_PPU_TO_APU_ACK     0x00002000
+#define IRQ_HPU_TO_PPU         0x00004000
+#define IRQ_PPU_TO_HPU_ACK     0x00004000
+#define IRQ_EPU_TO_PPU         0x00008000
+#define IRQ_PPU_TO_EPU_ACK     0x00008000
+
+#define IRQ_CPU_TO_EPU         0x00010000
+#define IRQ_EPU_TO_CPU_ACK     0x00010000
+#define IRQ_APU_TO_EPU         0x00020000
+#define IRQ_EPU_TO_APU_ACK     0x00020000
+#define IRQ_HPU_TO_EPU         0x00040000
+#define IRQ_EPU_TO_HPU_ACK     0x00040000
+#define IRQ_PPU_TO_EPU         0x00080000
+#define IRQ_EPU_TO_PPU_ACK     0x00080000
+
+#define SCB_OFFSET  0xDC0000
+
+/* If Firmware uses fixed memory map, it shall not allocate the area
+   between SCB_OFFSET and SCB_OFFSET+SCB_RESERVED_SIZE-1 inclusive */
+#define SCB_RESERVED_SIZE 0x10000
+
+
+/* This structure is used by EPU to provide memory descriptors in its memory */
+struct cx18_mdl {
+    u32 paddr;  /* Physical address of a buffer segment */
+    u32 length; /* Length of the buffer segment */
+};
+
+/* This structure is used by CPU to provide completed buffers information */
+struct cx18_mdl_ack {
+    u32 id;        /* ID of a completed MDL */
+    u32 data_used; /* Total data filled in the MDL for buffer 'id' */
+};
+
+struct cx18_scb {
+       /* These fields form the System Control Block which is used at boot time
+          for localizing the IPC data as well as the code positions for all
+          processors. The offsets are from the start of this struct. */
+
+       /* Offset where to find the Inter-Processor Communication data */
+       u32 ipc_offset;
+       u32 reserved01[7];
+       /* Offset where to find the start of the CPU code */
+       u32 cpu_code_offset;
+       u32 reserved02[3];
+       /* Offset where to find the start of the APU code */
+       u32 apu_code_offset;
+       u32 reserved03[3];
+       /* Offset where to find the start of the HPU code */
+       u32 hpu_code_offset;
+       u32 reserved04[3];
+       /* Offset where to find the start of the PPU code */
+       u32 ppu_code_offset;
+       u32 reserved05[3];
+
+       /* These fields form Inter-Processor Communication data which is used
+          by all processors to locate the information needed for communicating
+          with other processors */
+
+       /* Fields for CPU: */
+
+       /* bit 0: 1/0 processor ready/not ready. Set other bits to 0. */
+       u32 cpu_state;
+       u32 reserved1[7];
+       /* Offset to the mailbox used for sending commands from APU to CPU */
+       u32 apu2cpu_mb_offset;
+       /* Value to write to register SW1 register set (0xC7003100) after the
+          command is ready */
+       u32 apu2cpu_irq;
+       /* Value to write to register SW2 register set (0xC7003140) after the
+          command is cleared */
+       u32 apu2cpu_irq_ack;
+       u32 reserved2[13];
+
+       u32 hpu2cpu_mb_offset;
+       u32 hpu2cpu_irq;
+       u32 hpu2cpu_irq_ack;
+       u32 reserved3[13];
+
+       u32 ppu2cpu_mb_offset;
+       u32 ppu2cpu_irq;
+       u32 ppu2cpu_irq_ack;
+       u32 reserved4[13];
+
+       u32 epu2cpu_mb_offset;
+       u32 epu2cpu_irq;
+       u32 epu2cpu_irq_ack;
+       u32 reserved5[13];
+       u32 reserved6[8];
+
+       /* Fields for APU: */
+
+       u32 apu_state;
+       u32 reserved11[7];
+       u32 cpu2apu_mb_offset;
+       u32 cpu2apu_irq;
+       u32 cpu2apu_irq_ack;
+       u32 reserved12[13];
+
+       u32 hpu2apu_mb_offset;
+       u32 hpu2apu_irq;
+       u32 hpu2apu_irq_ack;
+       u32 reserved13[13];
+
+       u32 ppu2apu_mb_offset;
+       u32 ppu2apu_irq;
+       u32 ppu2apu_irq_ack;
+       u32 reserved14[13];
+
+       u32 epu2apu_mb_offset;
+       u32 epu2apu_irq;
+       u32 epu2apu_irq_ack;
+       u32 reserved15[13];
+       u32 reserved16[8];
+
+       /* Fields for HPU: */
+
+       u32 hpu_state;
+       u32 reserved21[7];
+       u32 cpu2hpu_mb_offset;
+       u32 cpu2hpu_irq;
+       u32 cpu2hpu_irq_ack;
+       u32 reserved22[13];
+
+       u32 apu2hpu_mb_offset;
+       u32 apu2hpu_irq;
+       u32 apu2hpu_irq_ack;
+       u32 reserved23[13];
+
+       u32 ppu2hpu_mb_offset;
+       u32 ppu2hpu_irq;
+       u32 ppu2hpu_irq_ack;
+       u32 reserved24[13];
+
+       u32 epu2hpu_mb_offset;
+       u32 epu2hpu_irq;
+       u32 epu2hpu_irq_ack;
+       u32 reserved25[13];
+       u32 reserved26[8];
+
+       /* Fields for PPU: */
+
+       u32 ppu_state;
+       u32 reserved31[7];
+       u32 cpu2ppu_mb_offset;
+       u32 cpu2ppu_irq;
+       u32 cpu2ppu_irq_ack;
+       u32 reserved32[13];
+
+       u32 apu2ppu_mb_offset;
+       u32 apu2ppu_irq;
+       u32 apu2ppu_irq_ack;
+       u32 reserved33[13];
+
+       u32 hpu2ppu_mb_offset;
+       u32 hpu2ppu_irq;
+       u32 hpu2ppu_irq_ack;
+       u32 reserved34[13];
+
+       u32 epu2ppu_mb_offset;
+       u32 epu2ppu_irq;
+       u32 epu2ppu_irq_ack;
+       u32 reserved35[13];
+       u32 reserved36[8];
+
+       /* Fields for EPU: */
+
+       u32 epu_state;
+       u32 reserved41[7];
+       u32 cpu2epu_mb_offset;
+       u32 cpu2epu_irq;
+       u32 cpu2epu_irq_ack;
+       u32 reserved42[13];
+
+       u32 apu2epu_mb_offset;
+       u32 apu2epu_irq;
+       u32 apu2epu_irq_ack;
+       u32 reserved43[13];
+
+       u32 hpu2epu_mb_offset;
+       u32 hpu2epu_irq;
+       u32 hpu2epu_irq_ack;
+       u32 reserved44[13];
+
+       u32 ppu2epu_mb_offset;
+       u32 ppu2epu_irq;
+       u32 ppu2epu_irq_ack;
+       u32 reserved45[13];
+       u32 reserved46[8];
+
+       u32 semaphores[8];  /* Semaphores */
+
+       u32 reserved50[32]; /* Reserved for future use */
+
+       struct cx18_mailbox  apu2cpu_mb;
+       struct cx18_mailbox  hpu2cpu_mb;
+       struct cx18_mailbox  ppu2cpu_mb;
+       struct cx18_mailbox  epu2cpu_mb;
+
+       struct cx18_mailbox  cpu2apu_mb;
+       struct cx18_mailbox  hpu2apu_mb;
+       struct cx18_mailbox  ppu2apu_mb;
+       struct cx18_mailbox  epu2apu_mb;
+
+       struct cx18_mailbox  cpu2hpu_mb;
+       struct cx18_mailbox  apu2hpu_mb;
+       struct cx18_mailbox  ppu2hpu_mb;
+       struct cx18_mailbox  epu2hpu_mb;
+
+       struct cx18_mailbox  cpu2ppu_mb;
+       struct cx18_mailbox  apu2ppu_mb;
+       struct cx18_mailbox  hpu2ppu_mb;
+       struct cx18_mailbox  epu2ppu_mb;
+
+       struct cx18_mailbox  cpu2epu_mb;
+       struct cx18_mailbox  apu2epu_mb;
+       struct cx18_mailbox  hpu2epu_mb;
+       struct cx18_mailbox  ppu2epu_mb;
+
+       struct cx18_mdl_ack  cpu_mdl_ack[CX18_MAX_STREAMS][2];
+       struct cx18_mdl      cpu_mdl[1];
+};
+
+void cx18_init_scb(struct cx18 *cx);
+
+#endif
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
new file mode 100644 (file)
index 0000000..afb141b
--- /dev/null
@@ -0,0 +1,566 @@
+/*
+ *  cx18 init/start/stop/exit stream functions
+ *
+ *  Derived from ivtv-streams.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 "cx18-driver.h"
+#include "cx18-fileops.h"
+#include "cx18-mailbox.h"
+#include "cx18-i2c.h"
+#include "cx18-queue.h"
+#include "cx18-ioctl.h"
+#include "cx18-streams.h"
+#include "cx18-cards.h"
+#include "cx18-scb.h"
+#include "cx18-av-core.h"
+#include "cx18-dvb.h"
+
+#define CX18_DSP0_INTERRUPT_MASK       0xd0004C
+
+static struct file_operations cx18_v4l2_enc_fops = {
+      .owner = THIS_MODULE,
+      .read = cx18_v4l2_read,
+      .open = cx18_v4l2_open,
+      .ioctl = cx18_v4l2_ioctl,
+      .release = cx18_v4l2_close,
+      .poll = cx18_v4l2_enc_poll,
+};
+
+/* offset from 0 to register ts v4l2 minors on */
+#define CX18_V4L2_ENC_TS_OFFSET   16
+/* offset from 0 to register pcm v4l2 minors on */
+#define CX18_V4L2_ENC_PCM_OFFSET  24
+/* offset from 0 to register yuv v4l2 minors on */
+#define CX18_V4L2_ENC_YUV_OFFSET  32
+
+static struct {
+       const char *name;
+       int vfl_type;
+       int minor_offset;
+       int dma;
+       enum v4l2_buf_type buf_type;
+       struct file_operations *fops;
+} cx18_stream_info[] = {
+       {       /* CX18_ENC_STREAM_TYPE_MPG */
+               "encoder MPEG",
+               VFL_TYPE_GRABBER, 0,
+               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               &cx18_v4l2_enc_fops
+       },
+       {       /* CX18_ENC_STREAM_TYPE_TS */
+               "TS",
+               VFL_TYPE_GRABBER, -1,
+               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               &cx18_v4l2_enc_fops
+       },
+       {       /* CX18_ENC_STREAM_TYPE_YUV */
+               "encoder YUV",
+               VFL_TYPE_GRABBER, CX18_V4L2_ENC_YUV_OFFSET,
+               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               &cx18_v4l2_enc_fops
+       },
+       {       /* CX18_ENC_STREAM_TYPE_VBI */
+               "encoder VBI",
+               VFL_TYPE_VBI, 0,
+               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VBI_CAPTURE,
+               &cx18_v4l2_enc_fops
+       },
+       {       /* CX18_ENC_STREAM_TYPE_PCM */
+               "encoder PCM audio",
+               VFL_TYPE_GRABBER, CX18_V4L2_ENC_PCM_OFFSET,
+               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_PRIVATE,
+               &cx18_v4l2_enc_fops
+       },
+       {       /* CX18_ENC_STREAM_TYPE_IDX */
+               "encoder IDX",
+               VFL_TYPE_GRABBER, -1,
+               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               &cx18_v4l2_enc_fops
+       },
+       {       /* CX18_ENC_STREAM_TYPE_RAD */
+               "encoder radio",
+               VFL_TYPE_RADIO, 0,
+               PCI_DMA_NONE, V4L2_BUF_TYPE_PRIVATE,
+               &cx18_v4l2_enc_fops
+       },
+};
+
+static void cx18_stream_init(struct cx18 *cx, int type)
+{
+       struct cx18_stream *s = &cx->streams[type];
+       struct video_device *dev = s->v4l2dev;
+       u32 max_size = cx->options.megabytes[type] * 1024 * 1024;
+
+       /* we need to keep v4l2dev, so restore it afterwards */
+       memset(s, 0, sizeof(*s));
+       s->v4l2dev = dev;
+
+       /* initialize cx18_stream fields */
+       s->cx = cx;
+       s->type = type;
+       s->name = cx18_stream_info[type].name;
+       s->handle = 0xffffffff;
+
+       s->dma = cx18_stream_info[type].dma;
+       s->buf_size = cx->stream_buf_size[type];
+       if (s->buf_size)
+               s->buffers = max_size / s->buf_size;
+       if (s->buffers > 63) {
+               /* Each stream has a maximum of 63 buffers,
+                  ensure we do not exceed that. */
+               s->buffers = 63;
+               s->buf_size = (max_size / s->buffers) & ~0xfff;
+       }
+       spin_lock_init(&s->qlock);
+       init_waitqueue_head(&s->waitq);
+       s->id = -1;
+       cx18_queue_init(&s->q_free);
+       cx18_queue_init(&s->q_full);
+       cx18_queue_init(&s->q_io);
+}
+
+static int cx18_prep_dev(struct cx18 *cx, int type)
+{
+       struct cx18_stream *s = &cx->streams[type];
+       u32 cap = cx->v4l2_cap;
+       int minor_offset = cx18_stream_info[type].minor_offset;
+       int minor;
+
+       /* These four fields are always initialized. If v4l2dev == NULL, then
+          this stream is not in use. In that case no other fields but these
+          four can be used. */
+       s->v4l2dev = NULL;
+       s->cx = cx;
+       s->type = type;
+       s->name = cx18_stream_info[type].name;
+
+       /* Check whether the radio is supported */
+       if (type == CX18_ENC_STREAM_TYPE_RAD && !(cap & V4L2_CAP_RADIO))
+               return 0;
+
+       /* Check whether VBI is supported */
+       if (type == CX18_ENC_STREAM_TYPE_VBI &&
+           !(cap & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE)))
+               return 0;
+
+       /* card number + user defined offset + device offset */
+       minor = cx->num + cx18_first_minor + minor_offset;
+
+       /* User explicitly selected 0 buffers for these streams, so don't
+          create them. */
+       if (cx18_stream_info[type].dma != PCI_DMA_NONE &&
+           cx->options.megabytes[type] == 0) {
+               CX18_INFO("Disabled %s device\n", cx18_stream_info[type].name);
+               return 0;
+       }
+
+       cx18_stream_init(cx, type);
+
+       if (minor_offset == -1)
+               return 0;
+
+       /* allocate and initialize the v4l2 video device structure */
+       s->v4l2dev = video_device_alloc();
+       if (s->v4l2dev == NULL) {
+               CX18_ERR("Couldn't allocate v4l2 video_device for %s\n",
+                               s->name);
+               return -ENOMEM;
+       }
+
+       s->v4l2dev->type =
+               VID_TYPE_CAPTURE | VID_TYPE_TUNER | VID_TYPE_TELETEXT |
+               VID_TYPE_CLIPPING | VID_TYPE_SCALES | VID_TYPE_MPEG_ENCODER;
+       snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "cx18%d %s",
+                       cx->num, s->name);
+
+       s->v4l2dev->minor = minor;
+       s->v4l2dev->dev = &cx->dev->dev;
+       s->v4l2dev->fops = cx18_stream_info[type].fops;
+       s->v4l2dev->release = video_device_release;
+
+       return 0;
+}
+
+/* Initialize v4l2 variables and register v4l2 devices */
+int cx18_streams_setup(struct cx18 *cx)
+{
+       int type;
+
+       /* Setup V4L2 Devices */
+       for (type = 0; type < CX18_MAX_STREAMS; type++) {
+               /* Prepare device */
+               if (cx18_prep_dev(cx, type))
+                       break;
+
+               /* Allocate Stream */
+               if (cx18_stream_alloc(&cx->streams[type]))
+                       break;
+       }
+       if (type == CX18_MAX_STREAMS)
+               return 0;
+
+       /* One or more streams could not be initialized. Clean 'em all up. */
+       cx18_streams_cleanup(cx);
+       return -ENOMEM;
+}
+
+static int cx18_reg_dev(struct cx18 *cx, int type)
+{
+       struct cx18_stream *s = &cx->streams[type];
+       int vfl_type = cx18_stream_info[type].vfl_type;
+       int minor;
+
+       /* TODO: Shouldn't this be a VFL_TYPE_TRANSPORT or something?
+        * We need a VFL_TYPE_TS defined.
+        */
+       if (strcmp("TS", s->name) == 0) {
+               /* just return if no DVB is supported */
+               if ((cx->card->hw_all & CX18_HW_DVB) == 0)
+                       return 0;
+               if (cx18_dvb_register(s) < 0) {
+                       CX18_ERR("DVB failed to register\n");
+                       return -EINVAL;
+               }
+       }
+
+       if (s->v4l2dev == NULL)
+               return 0;
+
+       minor = s->v4l2dev->minor;
+
+       /* Register device. First try the desired minor, then any free one. */
+       if (video_register_device(s->v4l2dev, vfl_type, minor) &&
+                       video_register_device(s->v4l2dev, vfl_type, -1)) {
+               CX18_ERR("Couldn't register v4l2 device for %s minor %d\n",
+                       s->name, minor);
+               video_device_release(s->v4l2dev);
+               s->v4l2dev = NULL;
+               return -ENOMEM;
+       }
+       minor = s->v4l2dev->minor;
+
+       switch (vfl_type) {
+       case VFL_TYPE_GRABBER:
+               CX18_INFO("Registered device video%d for %s (%d MB)\n",
+                       minor, s->name, cx->options.megabytes[type]);
+               break;
+
+       case VFL_TYPE_RADIO:
+               CX18_INFO("Registered device radio%d for %s\n",
+                       minor - MINOR_VFL_TYPE_RADIO_MIN, s->name);
+               break;
+
+       case VFL_TYPE_VBI:
+               if (cx->options.megabytes[type])
+                       CX18_INFO("Registered device vbi%d for %s (%d MB)\n",
+                               minor - MINOR_VFL_TYPE_VBI_MIN,
+                               s->name, cx->options.megabytes[type]);
+               else
+                       CX18_INFO("Registered device vbi%d for %s\n",
+                               minor - MINOR_VFL_TYPE_VBI_MIN, s->name);
+               break;
+       }
+
+       return 0;
+}
+
+/* Register v4l2 devices */
+int cx18_streams_register(struct cx18 *cx)
+{
+       int type;
+       int err = 0;
+
+       /* Register V4L2 devices */
+       for (type = 0; type < CX18_MAX_STREAMS; type++)
+               err |= cx18_reg_dev(cx, type);
+
+       if (err == 0)
+               return 0;
+
+       /* One or more streams could not be initialized. Clean 'em all up. */
+       cx18_streams_cleanup(cx);
+       return -ENOMEM;
+}
+
+/* Unregister v4l2 devices */
+void cx18_streams_cleanup(struct cx18 *cx)
+{
+       struct video_device *vdev;
+       int type;
+
+       /* Teardown all streams */
+       for (type = 0; type < CX18_MAX_STREAMS; type++) {
+               if (cx->streams[type].dvb.enabled)
+                       cx18_dvb_unregister(&cx->streams[type]);
+
+               vdev = cx->streams[type].v4l2dev;
+
+               cx->streams[type].v4l2dev = NULL;
+               if (vdev == NULL)
+                       continue;
+
+               cx18_stream_free(&cx->streams[type]);
+
+               /* Unregister device */
+               video_unregister_device(vdev);
+       }
+}
+
+static void cx18_vbi_setup(struct cx18_stream *s)
+{
+       struct cx18 *cx = s->cx;
+       int raw = cx->vbi.sliced_in->service_set == 0;
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       int lines;
+
+       if (cx->is_60hz) {
+               cx->vbi.count = 12;
+               cx->vbi.start[0] = 10;
+               cx->vbi.start[1] = 273;
+       } else {        /* PAL/SECAM */
+               cx->vbi.count = 18;
+               cx->vbi.start[0] = 6;
+               cx->vbi.start[1] = 318;
+       }
+
+       /* setup VBI registers */
+       cx18_av_cmd(cx, VIDIOC_S_FMT, &cx->vbi.in);
+
+       /* determine number of lines and total number of VBI bytes.
+          A raw line takes 1443 bytes: 2 * 720 + 4 byte frame header - 1
+          The '- 1' byte is probably an unused U or V byte. Or something...
+          A sliced line takes 51 bytes: 4 byte frame header, 4 byte internal
+          header, 42 data bytes + checksum (to be confirmed) */
+       if (raw) {
+               lines = cx->vbi.count * 2;
+       } else {
+               lines = cx->is_60hz ? 24 : 38;
+               if (cx->is_60hz)
+                       lines += 2;
+       }
+
+       cx->vbi.enc_size = lines *
+               (raw ? cx->vbi.raw_size : cx->vbi.sliced_size);
+
+       data[0] = s->handle;
+       /* Lines per field */
+       data[1] = (lines / 2) | ((lines / 2) << 16);
+       /* bytes per line */
+       data[2] = (raw ? cx->vbi.raw_size : cx->vbi.sliced_size);
+       /* Every X number of frames a VBI interrupt arrives
+          (frames as in 25 or 30 fps) */
+       data[3] = 1;
+       /* Setup VBI for the cx25840 digitizer */
+       if (raw) {
+               data[4] = 0x20602060;
+               data[5] = 0x30703070;
+       } else {
+               data[4] = 0xB0F0B0F0;
+               data[5] = 0xA0E0A0E0;
+       }
+
+       CX18_DEBUG_INFO("Setup VBI h: %d lines %x bpl %d fr %d %x %x\n",
+                       data[0], data[1], data[2], data[3], data[4], data[5]);
+
+       if (s->type == CX18_ENC_STREAM_TYPE_VBI)
+               cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data);
+}
+
+int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
+{
+       u32 data[MAX_MB_ARGUMENTS];
+       struct cx18 *cx = s->cx;
+       struct list_head *p;
+       int ts = 0;
+       int captype = 0;
+
+       if (s->v4l2dev == NULL && s->dvb.enabled == 0)
+               return -EINVAL;
+
+       CX18_DEBUG_INFO("Start encoder stream %s\n", s->name);
+
+       switch (s->type) {
+       case CX18_ENC_STREAM_TYPE_MPG:
+               captype = CAPTURE_CHANNEL_TYPE_MPEG;
+               cx->mpg_data_received = cx->vbi_data_inserted = 0;
+               cx->dualwatch_jiffies = jiffies;
+               cx->dualwatch_stereo_mode = cx->params.audio_properties & 0x300;
+               cx->search_pack_header = 0;
+               break;
+
+       case CX18_ENC_STREAM_TYPE_TS:
+               captype = CAPTURE_CHANNEL_TYPE_TS;
+               ts = 1;
+               break;
+       case CX18_ENC_STREAM_TYPE_YUV:
+               captype = CAPTURE_CHANNEL_TYPE_YUV;
+               break;
+       case CX18_ENC_STREAM_TYPE_PCM:
+               captype = CAPTURE_CHANNEL_TYPE_PCM;
+               break;
+       case CX18_ENC_STREAM_TYPE_VBI:
+               captype = cx->vbi.sliced_in->service_set ?
+                   CAPTURE_CHANNEL_TYPE_SLICED_VBI : CAPTURE_CHANNEL_TYPE_VBI;
+               cx->vbi.frame = 0;
+               cx->vbi.inserted_frame = 0;
+               memset(cx->vbi.sliced_mpeg_size,
+                       0, sizeof(cx->vbi.sliced_mpeg_size));
+               break;
+       default:
+               return -EINVAL;
+       }
+       s->buffers_stolen = 0;
+
+       /* mute/unmute video */
+       cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2,
+                 s->handle, !!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags));
+
+       /* Clear Streamoff flags in case left from last capture */
+       clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+
+       cx18_vapi_result(cx, data, CX18_CREATE_TASK, 1, CPU_CMD_MASK_CAPTURE);
+       s->handle = data[0];
+       cx18_vapi(cx, CX18_CPU_SET_CHANNEL_TYPE, 2, s->handle, captype);
+
+       if (atomic_read(&cx->capturing) == 0 && !ts) {
+               /* Stuff from Windows, we don't know what it is */
+               cx18_vapi(cx, CX18_CPU_SET_VER_CROP_LINE, 2, s->handle, 0);
+               cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 3, 1);
+               cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 8, 0);
+               cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 4, 1);
+               cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, s->handle, 12);
+
+               cx18_vapi(cx, CX18_CPU_SET_CAPTURE_LINE_NO, 3,
+                              s->handle, cx->digitizer, cx->digitizer);
+
+               /* Setup VBI */
+               if (cx->v4l2_cap & V4L2_CAP_VBI_CAPTURE)
+                       cx18_vbi_setup(s);
+
+               /* assign program index info.
+                  Mask 7: select I/P/B, Num_req: 400 max */
+               cx18_vapi_result(cx, data, CX18_CPU_SET_INDEXTABLE, 1, 0);
+
+               /* Setup API for Stream */
+               cx2341x_update(cx, cx18_api_func, NULL, &cx->params);
+       }
+
+       if (atomic_read(&cx->capturing) == 0) {
+               clear_bit(CX18_F_I_EOS, &cx->i_flags);
+               write_reg(7, CX18_DSP0_INTERRUPT_MASK);
+       }
+
+       cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle,
+               (void *)&cx->scb->cpu_mdl_ack[s->type][0] - cx->enc_mem,
+               (void *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem);
+
+       list_for_each(p, &s->q_free.list) {
+               struct cx18_buffer *buf = list_entry(p, struct cx18_buffer, list);
+
+               writel(buf->dma_handle, &cx->scb->cpu_mdl[buf->id].paddr);
+               writel(s->buf_size, &cx->scb->cpu_mdl[buf->id].length);
+               cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
+                       (void *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, 1,
+                       buf->id, s->buf_size);
+       }
+       /* begin_capture */
+       if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) {
+               CX18_DEBUG_WARN("Error starting capture!\n");
+               cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
+               return -EINVAL;
+       }
+
+       /* you're live! sit back and await interrupts :) */
+       atomic_inc(&cx->capturing);
+       return 0;
+}
+
+void cx18_stop_all_captures(struct cx18 *cx)
+{
+       int i;
+
+       for (i = CX18_MAX_STREAMS - 1; i >= 0; i--) {
+               struct cx18_stream *s = &cx->streams[i];
+
+               if (s->v4l2dev == NULL && s->dvb.enabled == 0)
+                       continue;
+               if (test_bit(CX18_F_S_STREAMING, &s->s_flags))
+                       cx18_stop_v4l2_encode_stream(s, 0);
+       }
+}
+
+int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
+{
+       struct cx18 *cx = s->cx;
+       unsigned long then;
+
+       if (s->v4l2dev == NULL && s->dvb.enabled == 0)
+               return -EINVAL;
+
+       /* This function assumes that you are allowed to stop the capture
+          and that we are actually capturing */
+
+       CX18_DEBUG_INFO("Stop Capture\n");
+
+       if (atomic_read(&cx->capturing) == 0)
+               return 0;
+
+       if (s->type == CX18_ENC_STREAM_TYPE_MPG)
+               cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, !gop_end);
+       else
+               cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 1, s->handle);
+
+       then = jiffies;
+
+       if (s->type == CX18_ENC_STREAM_TYPE_MPG && gop_end) {
+               CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n");
+       }
+
+       atomic_dec(&cx->capturing);
+
+       /* Clear capture and no-read bits */
+       clear_bit(CX18_F_S_STREAMING, &s->s_flags);
+
+       cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
+       s->handle = 0xffffffff;
+
+       if (atomic_read(&cx->capturing) > 0)
+               return 0;
+
+       write_reg(5, CX18_DSP0_INTERRUPT_MASK);
+       wake_up(&s->waitq);
+
+       return 0;
+}
+
+u32 cx18_find_handle(struct cx18 *cx)
+{
+       int i;
+
+       /* find first available handle to be used for global settings */
+       for (i = 0; i < CX18_MAX_STREAMS; i++) {
+               struct cx18_stream *s = &cx->streams[i];
+
+               if (s->v4l2dev && s->handle)
+                       return s->handle;
+       }
+       return 0;
+}
diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h
new file mode 100644 (file)
index 0000000..8c7ba7d
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  cx18 init/start/stop/exit stream functions
+ *
+ *  Derived from ivtv-streams.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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
+ */
+
+u32 cx18_find_handle(struct cx18 *cx);
+int cx18_streams_setup(struct cx18 *cx);
+int cx18_streams_register(struct cx18 *cx);
+void cx18_streams_cleanup(struct cx18 *cx);
+
+/* Capture related */
+int cx18_start_v4l2_encode_stream(struct cx18_stream *s);
+int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end);
+
+void cx18_stop_all_captures(struct cx18 *cx);
diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c
new file mode 100644 (file)
index 0000000..22e76ee
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ *  cx18 Vertical Blank Interval support functions
+ *
+ *  Derived from ivtv-vbi.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 "cx18-driver.h"
+#include "cx18-vbi.h"
+#include "cx18-ioctl.h"
+#include "cx18-queue.h"
+#include "cx18-av-core.h"
+
+static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp)
+{
+       int line = 0;
+       int i;
+       u32 linemask[2] = { 0, 0 };
+       unsigned short size;
+       static const u8 mpeg_hdr_data[] = {
+               0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x0c, 0x66,
+               0x24, 0x01, 0x01, 0xd1, 0xd3, 0xfa, 0xff, 0xff,
+               0x00, 0x00, 0x01, 0xbd, 0x00, 0x1a, 0x84, 0x80,
+               0x07, 0x21, 0x00, 0x5d, 0x63, 0xa7, 0xff, 0xff
+       };
+       const int sd = sizeof(mpeg_hdr_data);   /* start of vbi data */
+       int idx = cx->vbi.frame % CX18_VBI_FRAMES;
+       u8 *dst = &cx->vbi.sliced_mpeg_data[idx][0];
+
+       for (i = 0; i < lines; i++) {
+               struct v4l2_sliced_vbi_data *sdata = cx->vbi.sliced_data + i;
+               int f, l;
+
+               if (sdata->id == 0)
+                       continue;
+
+               l = sdata->line - 6;
+               f = sdata->field;
+               if (f)
+                       l += 18;
+               if (l < 32)
+                       linemask[0] |= (1 << l);
+               else
+                       linemask[1] |= (1 << (l - 32));
+               dst[sd + 12 + line * 43] = cx18_service2vbi(sdata->id);
+               memcpy(dst + sd + 12 + line * 43 + 1, sdata->data, 42);
+               line++;
+       }
+       memcpy(dst, mpeg_hdr_data, sizeof(mpeg_hdr_data));
+       if (line == 36) {
+               /* All lines are used, so there is no space for the linemask
+                  (the max size of the VBI data is 36 * 43 + 4 bytes).
+                  So in this case we use the magic number 'ITV0'. */
+               memcpy(dst + sd, "ITV0", 4);
+               memcpy(dst + sd + 4, dst + sd + 12, line * 43);
+               size = 4 + ((43 * line + 3) & ~3);
+       } else {
+               memcpy(dst + sd, "cx0", 4);
+               memcpy(dst + sd + 4, &linemask[0], 8);
+               size = 12 + ((43 * line + 3) & ~3);
+       }
+       dst[4+16] = (size + 10) >> 8;
+       dst[5+16] = (size + 10) & 0xff;
+       dst[9+16] = 0x21 | ((pts_stamp >> 29) & 0x6);
+       dst[10+16] = (pts_stamp >> 22) & 0xff;
+       dst[11+16] = 1 | ((pts_stamp >> 14) & 0xff);
+       dst[12+16] = (pts_stamp >> 7) & 0xff;
+       dst[13+16] = 1 | ((pts_stamp & 0x7f) << 1);
+       cx->vbi.sliced_mpeg_size[idx] = sd + size;
+}
+
+/* Compress raw VBI format, removes leading SAV codes and surplus space
+   after the field.
+   Returns new compressed size. */
+static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size)
+{
+       u32 line_size = cx->vbi.raw_decoder_line_size;
+       u32 lines = cx->vbi.count;
+       u8 sav1 = cx->vbi.raw_decoder_sav_odd_field;
+       u8 sav2 = cx->vbi.raw_decoder_sav_even_field;
+       u8 *q = buf;
+       u8 *p;
+       int i;
+
+       for (i = 0; i < lines; i++) {
+               p = buf + i * line_size;
+
+               /* Look for SAV code */
+               if (p[0] != 0xff || p[1] || p[2] ||
+                   (p[3] != sav1 && p[3] != sav2))
+                       break;
+               memcpy(q, p + 4, line_size - 4);
+               q += line_size - 4;
+       }
+       return lines * (line_size - 4);
+}
+
+
+/* Compressed VBI format, all found sliced blocks put next to one another
+   Returns new compressed size */
+static u32 compress_sliced_buf(struct cx18 *cx, u32 line, u8 *buf,
+                              u32 size, u8 sav)
+{
+       u32 line_size = cx->vbi.sliced_decoder_line_size;
+       struct v4l2_decode_vbi_line vbi;
+       int i;
+
+       /* find the first valid line */
+       for (i = 0; i < size; i++, buf++) {
+               if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav)
+                       break;
+       }
+
+       size -= i;
+       if (size < line_size)
+               return line;
+       for (i = 0; i < size / line_size; i++) {
+               u8 *p = buf + i * line_size;
+
+               /* Look for SAV code  */
+               if (p[0] != 0xff || p[1] || p[2] || p[3] != sav)
+                       continue;
+               vbi.p = p + 4;
+               cx18_av_cmd(cx, VIDIOC_INT_DECODE_VBI_LINE, &vbi);
+               if (vbi.type) {
+                       cx->vbi.sliced_data[line].id = vbi.type;
+                       cx->vbi.sliced_data[line].field = vbi.is_second_field;
+                       cx->vbi.sliced_data[line].line = vbi.line;
+                       memcpy(cx->vbi.sliced_data[line].data, vbi.p, 42);
+                       line++;
+               }
+       }
+       return line;
+}
+
+void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf,
+                          u64 pts_stamp, int streamtype)
+{
+       u8 *p = (u8 *) buf->buf;
+       u32 size = buf->bytesused;
+       int lines;
+
+       if (streamtype != CX18_ENC_STREAM_TYPE_VBI)
+               return;
+
+       /* Raw VBI data */
+       if (cx->vbi.sliced_in->service_set == 0) {
+               u8 type;
+
+               cx18_buf_swap(buf);
+
+               type = p[3];
+
+               size = buf->bytesused = compress_raw_buf(cx, p, size);
+
+               /* second field of the frame? */
+               if (type == cx->vbi.raw_decoder_sav_even_field) {
+                       /* Dirty hack needed for backwards
+                          compatibility of old VBI software. */
+                       p += size - 4;
+                       memcpy(p, &cx->vbi.frame, 4);
+                       cx->vbi.frame++;
+               }
+               return;
+       }
+
+       /* Sliced VBI data with data insertion */
+       cx18_buf_swap(buf);
+
+       /* first field */
+       lines = compress_sliced_buf(cx, 0, p, size / 2,
+                       cx->vbi.sliced_decoder_sav_odd_field);
+       /* second field */
+       /* experimentation shows that the second half does not always
+          begin at the exact address. So start a bit earlier
+          (hence 32). */
+       lines = compress_sliced_buf(cx, lines, p + size / 2 - 32,
+                       size / 2 + 32, cx->vbi.sliced_decoder_sav_even_field);
+       /* always return at least one empty line */
+       if (lines == 0) {
+               cx->vbi.sliced_data[0].id = 0;
+               cx->vbi.sliced_data[0].line = 0;
+               cx->vbi.sliced_data[0].field = 0;
+               lines = 1;
+       }
+       buf->bytesused = size = lines * sizeof(cx->vbi.sliced_data[0]);
+       memcpy(p, &cx->vbi.sliced_data[0], size);
+
+       if (cx->vbi.insert_mpeg)
+               copy_vbi_data(cx, lines, pts_stamp);
+       cx->vbi.frame++;
+}
diff --git a/drivers/media/video/cx18/cx18-vbi.h b/drivers/media/video/cx18/cx18-vbi.h
new file mode 100644 (file)
index 0000000..c56ff7d
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ *  cx18 Vertical Blank Interval support functions
+ *
+ *  Derived from ivtv-vbi.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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
+ */
+
+void cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf,
+                          u64 pts_stamp, int streamtype);
+int cx18_used_line(struct cx18 *cx, int line, int field);
diff --git a/drivers/media/video/cx18/cx18-version.h b/drivers/media/video/cx18/cx18-version.h
new file mode 100644 (file)
index 0000000..d5c7a6f
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *  cx18 driver version information
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 CX18_VERSION_H
+#define CX18_VERSION_H
+
+#define CX18_DRIVER_NAME "cx18"
+#define CX18_DRIVER_VERSION_MAJOR 1
+#define CX18_DRIVER_VERSION_MINOR 0
+#define CX18_DRIVER_VERSION_PATCHLEVEL 0
+
+#define CX18_VERSION __stringify(CX18_DRIVER_VERSION_MAJOR) "." __stringify(CX18_DRIVER_VERSION_MINOR) "." __stringify(CX18_DRIVER_VERSION_PATCHLEVEL)
+#define CX18_DRIVER_VERSION KERNEL_VERSION(CX18_DRIVER_VERSION_MAJOR, \
+       CX18_DRIVER_VERSION_MINOR, CX18_DRIVER_VERSION_PATCHLEVEL)
+
+#endif
diff --git a/drivers/media/video/cx18/cx18-video.c b/drivers/media/video/cx18/cx18-video.c
new file mode 100644 (file)
index 0000000..2e5c419
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *  cx18 video interface functions
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 "cx18-driver.h"
+#include "cx18-video.h"
+#include "cx18-av-core.h"
+#include "cx18-cards.h"
+
+void cx18_video_set_io(struct cx18 *cx)
+{
+       struct v4l2_routing route;
+       int inp = cx->active_input;
+       u32 type;
+
+       route.input = cx->card->video_inputs[inp].video_input;
+       route.output = 0;
+       cx18_av_cmd(cx, VIDIOC_INT_S_VIDEO_ROUTING, &route);
+
+       type = cx->card->video_inputs[inp].video_type;
+
+       if (type == CX18_CARD_INPUT_VID_TUNER)
+               route.input = 0;  /* Tuner */
+       else if (type < CX18_CARD_INPUT_COMPOSITE1)
+               route.input = 2;  /* S-Video */
+       else
+               route.input = 1;  /* Composite */
+}
diff --git a/drivers/media/video/cx18/cx18-video.h b/drivers/media/video/cx18/cx18-video.h
new file mode 100644 (file)
index 0000000..529006a
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ *  cx18 video interface functions
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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
+ */
+
+void cx18_video_set_io(struct cx18 *cx);
diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/video/cx18/cx23418.h
new file mode 100644 (file)
index 0000000..33f78da
--- /dev/null
@@ -0,0 +1,458 @@
+/*
+ *  cx18 header containing common defines.
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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 CX23418_H
+#define CX23418_H
+
+#include <media/cx2341x.h>
+
+#define MGR_CMD_MASK                           0x40000000
+/* The MSB of the command code indicates that this is the completion of a
+   command */
+#define MGR_CMD_MASK_ACK                       (MGR_CMD_MASK | 0x80000000)
+
+/* Description: This command creates a new instance of a certain task
+   IN[0]  - Task ID. This is one of the XPU_CMD_MASK_YYY where XPU is
+           the processor on which the task YYY will be created
+   OUT[0] - Task handle. This handle is passed along with commands to
+           dispatch to the right instance of the task
+   ReturnCode - One of the ERR_SYS_... */
+#define CX18_CREATE_TASK                       (MGR_CMD_MASK | 0x0001)
+
+/* Description: This command destroys an instance of a task
+   IN[0] - Task handle. Hanlde of the task to destroy
+   ReturnCode - One of the ERR_SYS_... */
+#define CX18_DESTROY_TASK                      (MGR_CMD_MASK | 0x0002)
+
+/* All commands for CPU have the following mask set */
+#define CPU_CMD_MASK                           0x20000000
+#define CPU_CMD_MASK_ACK                       (CPU_CMD_MASK | 0x80000000)
+#define CPU_CMD_MASK_CAPTURE                   (CPU_CMD_MASK | 0x00020000)
+#define CPU_CMD_MASK_TS                        (CPU_CMD_MASK | 0x00040000)
+
+#define EPU_CMD_MASK                           0x02000000
+#define EPU_CMD_MASK_DEBUG                     (EPU_CMD_MASK | 0x000000)
+#define EPU_CMD_MASK_DE                        (EPU_CMD_MASK | 0x040000)
+
+/* Description: This command indicates that a Memory Descriptor List has been
+   filled with the requested channel type
+   IN[0] - Task handle. Handle of the task
+   IN[1] - Offset of the MDL_ACK from the beginning of the local DDR.
+   IN[2] - Number of CNXT_MDL_ACK structures in the array pointed to by IN[1]
+   ReturnCode - One of the ERR_DE_... */
+#define CX18_EPU_DMA_DONE                              (EPU_CMD_MASK_DE | 0x0001)
+
+/* Something interesting happened
+   IN[0] - A value to log
+   IN[1] - An offset of a string in the MiniMe memory;
+          0/zero/NULL means "I have nothing to say" */
+#define CX18_EPU_DEBUG                                 (EPU_CMD_MASK_DEBUG | 0x0003)
+
+/* Description: This command starts streaming with the set channel type
+   IN[0] - Task handle. Handle of the task to start
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_CAPTURE_START                 (CPU_CMD_MASK_CAPTURE | 0x0002)
+
+/* Description: This command stops streaming with the set channel type
+   IN[0] - Task handle. Handle of the task to stop
+   IN[1] - 0 = stop at end of GOP, 1 = stop at end of frame (MPEG only)
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_CAPTURE_STOP                  (CPU_CMD_MASK_CAPTURE | 0x0003)
+
+/* Description: This command pauses streaming with the set channel type
+   IN[0] - Task handle. Handle of the task to pause
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_CAPTURE_PAUSE                 (CPU_CMD_MASK_CAPTURE | 0x0007)
+
+/* Description: This command resumes streaming with the set channel type
+   IN[0] - Task handle. Handle of the task to resume
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_CAPTURE_RESUME                (CPU_CMD_MASK_CAPTURE | 0x0008)
+
+#define CAPTURE_CHANNEL_TYPE_NONE              0
+#define CAPTURE_CHANNEL_TYPE_MPEG              1
+#define CAPTURE_CHANNEL_TYPE_INDEX             2
+#define CAPTURE_CHANNEL_TYPE_YUV               3
+#define CAPTURE_CHANNEL_TYPE_PCM               4
+#define CAPTURE_CHANNEL_TYPE_VBI               5
+#define CAPTURE_CHANNEL_TYPE_SLICED_VBI                6
+#define CAPTURE_CHANNEL_TYPE_TS                        7
+#define CAPTURE_CHANNEL_TYPE_MAX               15
+
+/* Description: This command sets the channel type. This can only be done
+   when stopped.
+   IN[0] - Task handle. Handle of the task to start
+   IN[1] - Channel Type. See Below.
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_CHANNEL_TYPE                      (CPU_CMD_MASK_CAPTURE + 1)
+
+/* Description: Set stream output type
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - type
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_STREAM_OUTPUT_TYPE                (CPU_CMD_MASK_CAPTURE | 0x0012)
+
+/* Description: Set video input resolution and frame rate
+   IN[0] - task handle
+   IN[1] - reserved
+   IN[2] - reserved
+   IN[3] - reserved
+   IN[4] - reserved
+   IN[5] - frame rate, 0 - 29.97f/s, 1 - 25f/s
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VIDEO_IN                  (CPU_CMD_MASK_CAPTURE | 0x0004)
+
+/* Description: Set video frame rate
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - video bit rate mode
+   IN[2] - video average rate
+   IN[3] - video peak rate
+   IN[4] - system mux rate
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VIDEO_RATE                (CPU_CMD_MASK_CAPTURE | 0x0005)
+
+/* Description: Set video output resolution
+   IN[0] - task handle
+   IN[1] - horizontal size
+   IN[2] - vertical size
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VIDEO_RESOLUTION          (CPU_CMD_MASK_CAPTURE | 0x0006)
+
+/* Description: This command set filter parameters
+   IN[0] - Task handle. Handle of the task
+   IN[1] - type, 0 - temporal, 1 - spatial, 2 - median
+   IN[2] - mode,  temporal/spatial: 0 - disable, 1 - static, 2 - dynamic
+                       median: 0 = disable, 1 = horizontal, 2 = vertical,
+                               3 = horizontal/vertical, 4 = diagonal
+   IN[3] - strength, temporal 0 - 31, spatial 0 - 15
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_FILTER_PARAM              (CPU_CMD_MASK_CAPTURE | 0x0009)
+
+/* Description: This command set spatial filter type
+   IN[0] - Task handle.
+   IN[1] - luma type: 0 = disable, 1 = 1D horizontal only, 2 = 1D vertical only,
+                     3 = 2D H/V separable, 4 = 2D symmetric non-separable
+   IN[2] - chroma type: 0 - diable, 1 = 1D horizontal
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_SPATIAL_FILTER_TYPE       (CPU_CMD_MASK_CAPTURE | 0x000C)
+
+/* Description: This command set coring levels for median filter
+   IN[0] - Task handle.
+   IN[1] - luma_high
+   IN[2] - luma_low
+   IN[3] - chroma_high
+   IN[4] - chroma_low
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_MEDIAN_CORING             (CPU_CMD_MASK_CAPTURE | 0x000E)
+
+/* Description: This command set the picture type mask for index file
+   IN[0] -     0 = disable index file output
+                       1 = output I picture
+                       2 = P picture
+                       4 = B picture
+                       other = illegal */
+#define CX18_CPU_SET_INDEXTABLE                (CPU_CMD_MASK_CAPTURE | 0x0010)
+
+/* Description: Set audio parameters
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - audio parameter
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_AUDIO_PARAMETERS          (CPU_CMD_MASK_CAPTURE | 0x0011)
+
+/* Description: Set video mute
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - bit31-24: muteYvalue
+          bit23-16: muteUvalue
+          bit15-8:  muteVvalue
+          bit0:     1:mute, 0: unmute
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VIDEO_MUTE                        (CPU_CMD_MASK_CAPTURE | 0x0013)
+
+/* Description: Set audio mute
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - mute/unmute
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_AUDIO_MUTE                        (CPU_CMD_MASK_CAPTURE | 0x0014)
+
+/* Description: Set stream output type
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - subType
+           SET_INITIAL_SCR                     1
+           SET_QUALITY_MODE            2
+           SET_VIM_PROTECT_MODE        3
+           SET_PTS_CORRECTION          4
+           SET_USB_FLUSH_MODE          5
+           SET_MERAQPAR_ENABLE         6
+           SET_NAV_PACK_INSERTION      7
+           SET_SCENE_CHANGE_ENABLE     8
+   IN[2] - parameter 1
+   IN[3] - parameter 2
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_MISC_PARAMETERS           (CPU_CMD_MASK_CAPTURE | 0x0015)
+
+/* Description: Set raw VBI parameters
+   IN[0] - Task handle
+   IN[1] - No. of input lines per field:
+                               bit[15:0]: field 1,
+                               bit[31:16]: field 2
+   IN[2] - No. of input bytes per line
+   IN[3] - No. of output frames per transfer
+   IN[4] - start code
+   IN[5] - stop code
+   ReturnCode */
+#define CX18_CPU_SET_RAW_VBI_PARAM             (CPU_CMD_MASK_CAPTURE | 0x0016)
+
+/* Description: Set capture line No.
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - height1
+   IN[2] - height2
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_CAPTURE_LINE_NO           (CPU_CMD_MASK_CAPTURE | 0x0017)
+
+/* Description: Set copyright
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - copyright
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_COPYRIGHT                 (CPU_CMD_MASK_CAPTURE | 0x0018)
+
+/* Description: Set audio PID
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - PID
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_AUDIO_PID                 (CPU_CMD_MASK_CAPTURE | 0x0019)
+
+/* Description: Set video PID
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - PID
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VIDEO_PID                 (CPU_CMD_MASK_CAPTURE | 0x001A)
+
+/* Description: Set Vertical Crop Line
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - Line
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VER_CROP_LINE             (CPU_CMD_MASK_CAPTURE | 0x001B)
+
+/* Description: Set COP structure
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - M
+   IN[2] - N
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_GOP_STRUCTURE             (CPU_CMD_MASK_CAPTURE | 0x001C)
+
+/* Description: Set Scene Change Detection
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - scene change
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_SCENE_CHANGE_DETECTION    (CPU_CMD_MASK_CAPTURE | 0x001D)
+
+/* Description: Set Aspect Ratio
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - AspectRatio
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_ASPECT_RATIO              (CPU_CMD_MASK_CAPTURE | 0x001E)
+
+/* Description: Set Skip Input Frame
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - skip input frames
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_SKIP_INPUT_FRAME          (CPU_CMD_MASK_CAPTURE | 0x001F)
+
+/* Description: Set sliced VBI parameters -
+   Note This API will only apply to MPEG and Sliced VBI Channels
+   IN[0] - Task handle
+   IN[1] - output type, 0 - CC, 1 - Moji, 2 - Teletext
+   IN[2] - start / stop line
+                       bit[15:0] start line number
+                       bit[31:16] stop line number
+   IN[3] - number of output frames per interrupt
+   IN[4] - VBI insertion mode
+                       bit 0:  output user data, 1 - enable
+                       bit 1:  output private stream, 1 - enable
+                       bit 2:  mux option, 0 - in GOP, 1 - in picture
+                       bit[7:0]        private stream ID
+   IN[5] - insertion period while mux option is in picture
+   ReturnCode - VBI data offset */
+#define CX18_CPU_SET_SLICED_VBI_PARAM          (CPU_CMD_MASK_CAPTURE | 0x0020)
+
+/* Description: Set the user data place holder
+   IN[0] - type of data (0 for user)
+   IN[1] - Stuffing period
+   IN[2] - ID data size in word (less than 10)
+   IN[3] - Pointer to ID buffer */
+#define CX18_CPU_SET_USERDATA_PLACE_HOLDER     (CPU_CMD_MASK_CAPTURE | 0x0021)
+
+
+/* Description:
+   In[0] Task Handle
+   return parameter:
+   Out[0]  Reserved
+   Out[1]  Video PTS bit[32:2] of last output video frame.
+   Out[2]  Video PTS bit[ 1:0] of last output video frame.
+   Out[3]  Hardware Video PTS counter bit[31:0],
+            these bits get incremented on every 90kHz clock tick.
+   Out[4]  Hardware Video PTS counter bit32,
+            these bits get incremented on every 90kHz clock tick.
+   ReturnCode */
+#define CX18_CPU_GET_ENC_PTS                   (CPU_CMD_MASK_CAPTURE | 0x0022)
+
+/* Below is the list of commands related to the data exchange */
+#define CPU_CMD_MASK_DE                        (CPU_CMD_MASK | 0x040000)
+
+/* Description: This command provides the physical base address of the local
+   DDR as viewed by EPU
+   IN[0] - Physical offset where EPU has the local DDR mapped
+   ReturnCode - One of the ERR_DE_... */
+#define CPU_CMD_DE_SetBase                     (CPU_CMD_MASK_DE | 0x0001)
+
+/* Description: This command provides the offsets in the device memory where
+   the 2 cx18_mdl_ack blocks reside
+   IN[0] - Task handle. Handle of the task to start
+   IN[1] - Offset of the first cx18_mdl_ack from the beginning of the
+          local DDR.
+   IN[2] - Offset of the second cx18_mdl_ack from the beginning of the
+          local DDR.
+   ReturnCode - One of the ERR_DE_... */
+#define CX18_CPU_DE_SET_MDL_ACK                        (CPU_CMD_MASK_DE | 0x0002)
+
+/* Description: This command provides the offset to a Memory Descriptor List
+   IN[0] - Task handle. Handle of the task to start
+   IN[1] - Offset of the MDL from the beginning of the local DDR.
+   IN[2] - Number of cx18_mdl structures in the array pointed to by IN[1]
+   IN[3] - Buffer ID
+   IN[4] - Total buffer length
+   ReturnCode - One of the ERR_DE_... */
+#define CX18_CPU_DE_SET_MDL                    (CPU_CMD_MASK_DE | 0x0005)
+
+/* Description: This command requests return of all current Memory
+   Descriptor Lists to the driver
+   IN[0] - Task handle. Handle of the task to start
+   ReturnCode - One of the ERR_DE_... */
+/* #define CX18_CPU_DE_ReleaseMDL               (CPU_CMD_MASK_DE | 0x0006) */
+
+/* Description: This command signals the cpu that the dat buffer has been
+   consumed and ready for re-use.
+   IN[0] - Task handle. Handle of the task
+   IN[1] - Offset of the data block from the beginning of the local DDR.
+   IN[2] - Number of bytes in the data block
+   ReturnCode - One of the ERR_DE_... */
+/* #define CX18_CPU_DE_RELEASE_BUFFER           (CPU_CMD_MASK_DE | 0x0007) */
+
+/* No Error / Success */
+#define CNXT_OK                 0x000000
+
+/* Received unknown command */
+#define CXERR_UNK_CMD           0x000001
+
+/* First parameter in the command is invalid */
+#define CXERR_INVALID_PARAM1    0x000002
+
+/* Second parameter in the command is invalid */
+#define CXERR_INVALID_PARAM2    0x000003
+
+/* Device interface is not open/found */
+#define CXERR_DEV_NOT_FOUND     0x000004
+
+/* Requested function is not implemented/available */
+#define CXERR_NOTSUPPORTED      0x000005
+
+/* Invalid pointer is provided */
+#define CXERR_BADPTR            0x000006
+
+/* Unable to allocate memory */
+#define CXERR_NOMEM             0x000007
+
+/* Object/Link not found */
+#define CXERR_LINK              0x000008
+
+/* Device busy, command cannot be executed */
+#define CXERR_BUSY              0x000009
+
+/* File/device/handle is not open. */
+#define CXERR_NOT_OPEN          0x00000A
+
+/* Value is out of range */
+#define CXERR_OUTOFRANGE        0x00000B
+
+/* Buffer overflow */
+#define CXERR_OVERFLOW          0x00000C
+
+/* Version mismatch */
+#define CXERR_BADVER            0x00000D
+
+/* Operation timed out */
+#define CXERR_TIMEOUT           0x00000E
+
+/* Operation aborted */
+#define CXERR_ABORT             0x00000F
+
+/* Specified I2C device not found for read/write */
+#define CXERR_I2CDEV_NOTFOUND   0x000010
+
+/* Error in I2C data xfer (but I2C device is present) */
+#define CXERR_I2CDEV_XFERERR    0x000011
+
+/* Chanel changing component not ready */
+#define CXERR_CHANNELNOTREADY   0x000012
+
+/* PPU (Presensation/Decoder) mail box is corrupted */
+#define CXERR_PPU_MB_CORRUPT    0x000013
+
+/* CPU (Capture/Encoder) mail box is corrupted */
+#define CXERR_CPU_MB_CORRUPT    0x000014
+
+/* APU (Audio) mail box is corrupted */
+#define CXERR_APU_MB_CORRUPT    0x000015
+
+/* Unable to open file for reading */
+#define CXERR_FILE_OPEN_READ    0x000016
+
+/* Unable to open file for writing */
+#define CXERR_FILE_OPEN_WRITE   0x000017
+
+/* Unable to find the I2C section specified */
+#define CXERR_I2C_BADSECTION    0x000018
+
+/* Error in I2C data xfer (but I2C device is present) */
+#define CXERR_I2CDEV_DATALOW    0x000019
+
+/* Error in I2C data xfer (but I2C device is present) */
+#define CXERR_I2CDEV_CLOCKLOW   0x00001A
+
+/* No Interrupt received from HW (for I2C access) */
+#define CXERR_NO_HW_I2C_INTR    0x00001B
+
+/* RPU is not ready to accept commands! */
+#define CXERR_RPU_NOT_READY     0x00001C
+
+/* RPU is not ready to accept commands! */
+#define CXERR_RPU_NO_ACK        0x00001D
+
+/* The are no buffers ready. Try again soon! */
+#define CXERR_NODATA_AGAIN      0x00001E
+
+/* The stream is stopping. Function not alllowed now! */
+#define CXERR_STOPPING_STATUS   0x00001F
+
+/* Trying to access hardware when the power is turned OFF */
+#define CXERR_DEVPOWER_OFF      0x000020
+
+#endif /* CX23418_H */
index ca5fbce3a9095bc07dca912ce74e19387f5a4f02..cadf936c367351fb249bef07ac1a8c42a547c987 100644 (file)
@@ -4,19 +4,19 @@ config VIDEO_CX23885
        select I2C_ALGOBIT
        select FW_LOADER
        select VIDEO_BTCX
-       select VIDEO_TUNER
+       select MEDIA_TUNER
        select VIDEO_TVEEPROM
        select VIDEO_IR
        select VIDEOBUF_DVB
        select VIDEO_CX25840
-       select DVB_TUNER_MT2131 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_MT2131 if !DVB_FE_CUSTOMISE
        select DVB_S5H1409 if !DVB_FE_CUSTOMISE
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
        select DVB_PLL if !DVB_FE_CUSTOMISE
-       select TUNER_XC2028 if !DVB_FE_CUSTOMIZE
-       select TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
-       select DVB_TDA18271 if !DVB_FE_CUSTOMIZE
-       select DVB_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
+       select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE
+       select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
+       select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE
+       select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
        select DVB_TDA10048 if !DVB_FE_CUSTOMIZE
        ---help---
          This is a video4linux driver for Conexant 23885 based
index d7b0721af062611215e6b516ec5c86e970911414..29c23b44c13c95bd498c705c024024297f885914 100644 (file)
@@ -3,6 +3,7 @@ cx23885-objs    := cx23885-cards.o cx23885-video.o cx23885-vbi.o cx23885-core.o cx2
 obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
 
 EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
 
index 7fde678b2c4a5fbb0785af63a77cfbee86cb22d2..88823810497ca3c002fa53e25801551f911c30a4 100644 (file)
@@ -1209,7 +1209,8 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
 
 /* ----------------------------------------------------------------------- */
 
-static int cx25840_probe(struct i2c_client *client)
+static int cx25840_probe(struct i2c_client *client,
+                        const struct i2c_device_id *did)
 {
        struct cx25840_state *state;
        u32 id;
index 27635cdcbaf22d5457f419ff7e9b621dd77826ef..b0d7d6a7a4cc359dc725ee27b1ed3c5d87264d4e 100644 (file)
@@ -5,7 +5,7 @@ config VIDEO_CX88
        select FW_LOADER
        select VIDEO_BTCX
        select VIDEOBUF_DMA_SG
-       select VIDEO_TUNER
+       select MEDIA_TUNER
        select VIDEO_TVEEPROM
        select VIDEO_IR
        select VIDEO_WM8775 if VIDEO_HELPER_CHIPS_AUTO
@@ -57,7 +57,7 @@ config VIDEO_CX88_DVB
        select DVB_NXT200X if !DVB_FE_CUSTOMISE
        select DVB_CX24123 if !DVB_FE_CUSTOMISE
        select DVB_ISL6421 if !DVB_FE_CUSTOMISE
-       select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
        select DVB_S5H1411 if !DVB_FE_CUSTOMISE
        ---help---
          This adds support for DVB/ATSC cards based on the
index 532cee35eb3c4f49962cc4b627792f18798a113a..6ec30f242578984a4563c7ce5cc789c57e266502 100644 (file)
@@ -10,5 +10,6 @@ obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
 obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
 
 EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
index 2b6b283cda15b658c08d1841328350c80aa069f2..aeba26dc0a37ce69a8da26cd7fff176b139da54a 100644 (file)
@@ -57,6 +57,9 @@ MODULE_PARM_DESC(latency,"pci latency timer");
 /* ------------------------------------------------------------------ */
 /* board config info                                                  */
 
+/* If radio_type !=UNSET, radio_addr should be specified
+ */
+
 static const struct cx88_board cx88_boards[] = {
        [CX88_BOARD_UNKNOWN] = {
                .name           = "UNKNOWN/GENERIC",
@@ -2446,25 +2449,31 @@ EXPORT_SYMBOL_GPL(cx88_setup_xc3028);
 static void cx88_card_setup(struct cx88_core *core)
 {
        static u8 eeprom[256];
+       struct tuner_setup tun_setup;
+       unsigned int mode_mask = T_RADIO     |
+                                T_ANALOG_TV |
+                                T_DIGITAL_TV;
+
+       memset(&tun_setup, 0, sizeof(tun_setup));
 
        if (0 == core->i2c_rc) {
                core->i2c_client.addr = 0xa0 >> 1;
-               tveeprom_read(&core->i2c_client,eeprom,sizeof(eeprom));
+               tveeprom_read(&core->i2c_client, eeprom, sizeof(eeprom));
        }
 
        switch (core->boardnr) {
        case CX88_BOARD_HAUPPAUGE:
        case CX88_BOARD_HAUPPAUGE_ROSLYN:
                if (0 == core->i2c_rc)
-                       hauppauge_eeprom(core,eeprom+8);
+                       hauppauge_eeprom(core, eeprom+8);
                break;
        case CX88_BOARD_GDI:
                if (0 == core->i2c_rc)
-                       gdi_eeprom(core,eeprom);
+                       gdi_eeprom(core, eeprom);
                break;
        case CX88_BOARD_WINFAST2000XP_EXPERT:
                if (0 == core->i2c_rc)
-                       leadtek_eeprom(core,eeprom);
+                       leadtek_eeprom(core, eeprom);
                break;
        case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
        case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
@@ -2474,7 +2483,7 @@ static void cx88_card_setup(struct cx88_core *core)
        case CX88_BOARD_HAUPPAUGE_HVR3000:
        case CX88_BOARD_HAUPPAUGE_HVR1300:
                if (0 == core->i2c_rc)
-                       hauppauge_eeprom(core,eeprom);
+                       hauppauge_eeprom(core, eeprom);
                break;
        case CX88_BOARD_KWORLD_DVBS_100:
                cx_write(MO_GP0_IO, 0x000007f8);
@@ -2555,6 +2564,35 @@ static void cx88_card_setup(struct cx88_core *core)
 
                cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tea5767_cfg);
        }
+       } /*end switch() */
+
+
+       /* Setup tuners */
+       if ((core->board.radio_type != UNSET)) {
+               tun_setup.mode_mask      = T_RADIO;
+               tun_setup.type           = core->board.radio_type;
+               tun_setup.addr           = core->board.radio_addr;
+               tun_setup.tuner_callback = cx88_tuner_callback;
+               cx88_call_i2c_clients(core, TUNER_SET_TYPE_ADDR, &tun_setup);
+               mode_mask &= ~T_RADIO;
+       }
+
+       if (core->board.tuner_type != TUNER_ABSENT) {
+               tun_setup.mode_mask      = mode_mask;
+               tun_setup.type           = core->board.tuner_type;
+               tun_setup.addr           = core->board.tuner_addr;
+               tun_setup.tuner_callback = cx88_tuner_callback;
+
+               cx88_call_i2c_clients(core, TUNER_SET_TYPE_ADDR, &tun_setup);
+       }
+
+       if (core->board.tda9887_conf) {
+               struct v4l2_priv_tun_config tda9887_cfg;
+
+               tda9887_cfg.tuner = TUNER_TDA9887;
+               tda9887_cfg.priv  = &core->board.tda9887_conf;
+
+               cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &tda9887_cfg);
        }
 
        if (core->board.tuner_type == TUNER_XC2028) {
@@ -2572,6 +2610,7 @@ static void cx88_card_setup(struct cx88_core *core)
                            ctl.fname);
                cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &xc2028_cfg);
        }
+       cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL);
 }
 
 /* ------------------------------------------------------------------ */
@@ -2710,7 +2749,6 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
        if (TUNER_ABSENT != core->board.tuner_type)
                request_module("tuner");
 
-       cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL);
        cx88_card_setup(core);
        cx88_ir_init(core, pci);
 
index c6b44732a082fd743b6fbbc3ac39f4ab511e514f..cb6a096069c7b0fc7a0fcc093dc225d018948ba5 100644 (file)
@@ -99,42 +99,11 @@ static int cx8800_bit_getsda(void *data)
 
 static int attach_inform(struct i2c_client *client)
 {
-       struct tuner_setup tun_setup;
        struct cx88_core *core = i2c_get_adapdata(client->adapter);
 
        dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n",
                client->driver->driver.name, client->addr, client->name);
-       if (!client->driver->command)
-               return 0;
-
-       if (core->board.radio_type != UNSET) {
-               if ((core->board.radio_addr==ADDR_UNSET)||(core->board.radio_addr==client->addr)) {
-                       tun_setup.mode_mask      = T_RADIO;
-                       tun_setup.type           = core->board.radio_type;
-                       tun_setup.addr           = core->board.radio_addr;
-                       tun_setup.tuner_callback = cx88_tuner_callback;
-                       client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup);
-               }
-       }
-       if (core->board.tuner_type != UNSET) {
-               if ((core->board.tuner_addr==ADDR_UNSET)||(core->board.tuner_addr==client->addr)) {
-
-                       tun_setup.mode_mask      = T_ANALOG_TV;
-                       tun_setup.type           = core->board.tuner_type;
-                       tun_setup.addr           = core->board.tuner_addr;
-                       tun_setup.tuner_callback = cx88_tuner_callback;
-                       client->driver->command (client,TUNER_SET_TYPE_ADDR, &tun_setup);
-               }
-       }
-
-       if (core->board.tda9887_conf) {
-               struct v4l2_priv_tun_config tda9887_cfg;
 
-               tda9887_cfg.tuner = TUNER_TDA9887;
-               tda9887_cfg.priv  = &core->board.tda9887_conf;
-
-               client->driver->command(client, TUNER_SET_CONFIG, &tda9887_cfg);
-       }
        return 0;
 }
 
index 9caffed2b6b8302637cde0ad128c791cc5ce364e..c7c2896bbd8b312823d0abd9898c3ed8ee8e455f 100644 (file)
@@ -1,7 +1,7 @@
 config VIDEO_EM28XX
        tristate "Empia EM28xx USB video capture support"
        depends on VIDEO_DEV && I2C && INPUT
-       select VIDEO_TUNER
+       select MEDIA_TUNER
        select VIDEO_TVEEPROM
        select VIDEO_IR
        select VIDEOBUF_VMALLOC
index 3d1c3cc337fe65c7407d728afab04990bdcd4e98..8137a8c94bfc365a1d63ffd677cf8cd1ed236d60 100644 (file)
@@ -8,6 +8,7 @@ obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o
 obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o
 
 EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
 
index b6171702c4d051824c5215f5b93b9ca8f339cbc2..eec115bf9517a54342ea749323f14208020cd05f 100644 (file)
@@ -4,7 +4,7 @@ config VIDEO_IVTV
        select I2C_ALGOBIT
        select FW_LOADER
        select VIDEO_IR
-       select VIDEO_TUNER
+       select MEDIA_TUNER
        select VIDEO_TVEEPROM
        select VIDEO_CX2341X
        select VIDEO_CX25840
index a0389014fa88dc8dc156263e140232794b156e45..26ce0d6eaee1a3c15a918783130b26eb713827da 100644 (file)
@@ -8,6 +8,7 @@ obj-$(CONFIG_VIDEO_IVTV) += ivtv.o
 obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o
 
 EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
 
index e908649ea37cc738fc2611fb4cb14cbfe3a90ea0..4fb8faefe2ced9f54d6c08bca9d8cdff42e10000 100644 (file)
@@ -40,6 +40,8 @@
 #define MSP_MONO   MSP_INPUT(MSP_IN_MONO, MSP_IN_TUNER1, \
                                MSP_DSP_IN_SCART, MSP_DSP_IN_SCART)
 
+#define V4L2_STD_NOT_MN (V4L2_STD_PAL|V4L2_STD_SECAM)
+
 /* usual i2c tuner addresses to probe */
 static struct ivtv_card_tuner_i2c ivtv_i2c_std = {
        .radio = { I2C_CLIENT_END },
@@ -298,7 +300,7 @@ static const struct ivtv_card ivtv_card_mpg600 = {
        .gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 },
        .tuners = {
                /* The PAL tuner is confirmed */
-               { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FQ1216ME },
+               { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FQ1216ME },
                { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
        },
        .pci_list = ivtv_pci_mpg600,
@@ -339,7 +341,7 @@ static const struct ivtv_card ivtv_card_mpg160 = {
                              .lang1 = 0x0004, .lang2  = 0x0000, .both   = 0x0008 },
        .gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 },
        .tuners = {
-               { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FQ1216ME },
+               { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FQ1216ME },
                { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
        },
        .pci_list = ivtv_pci_mpg160,
@@ -375,7 +377,7 @@ static const struct ivtv_card ivtv_card_pg600 = {
                { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL },
        },
        .tuners = {
-               { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FQ1216ME },
+               { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FQ1216ME },
                { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
        },
        .pci_list = ivtv_pci_pg600,
@@ -416,7 +418,7 @@ static const struct ivtv_card ivtv_card_avc2410 = {
           on the country/region setting of the user to decide which tuner
           is available. */
        .tuners = {
-               { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+               { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
                { .std = V4L2_STD_ALL - V4L2_STD_NTSC_M_JP,
                        .tuner = TUNER_PHILIPS_FM1236_MK3 },
                { .std = V4L2_STD_NTSC_M_JP, .tuner = TUNER_PHILIPS_FQ1286 },
@@ -490,7 +492,7 @@ static const struct ivtv_card ivtv_card_tg5000tv = {
        .gpio_video_input  = { .mask = 0x0030, .tuner  = 0x0000,
                          .composite = 0x0010, .svideo = 0x0020 },
        .tuners = {
-               { .std = V4L2_STD_525_60, .tuner = TUNER_PHILIPS_FQ1286 },
+               { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
        },
        .pci_list = ivtv_pci_tg5000tv,
        .i2c = &ivtv_i2c_std,
@@ -521,7 +523,7 @@ static const struct ivtv_card ivtv_card_va2000 = {
                { IVTV_CARD_INPUT_AUD_TUNER, MSP_TUNER },
        },
        .tuners = {
-               { .std = V4L2_STD_525_60, .tuner = TUNER_PHILIPS_FQ1286 },
+               { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
        },
        .pci_list = ivtv_pci_va2000,
        .i2c = &ivtv_i2c_std,
@@ -565,7 +567,7 @@ static const struct ivtv_card ivtv_card_cx23416gyc = {
        .gpio_audio_freq   = { .mask = 0xc000, .f32000 = 0x0000,
                             .f44100 = 0x4000, .f48000 = 0x8000 },
        .tuners = {
-               { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+               { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
                { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
        },
        .pci_list = ivtv_pci_cx23416gyc,
@@ -597,7 +599,7 @@ static const struct ivtv_card ivtv_card_cx23416gyc_nogr = {
        .gpio_audio_freq   = { .mask = 0xc000, .f32000 = 0x0000,
                             .f44100 = 0x4000, .f48000 = 0x8000 },
        .tuners = {
-               { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+               { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
                { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
        },
        .i2c = &ivtv_i2c_std,
@@ -627,7 +629,7 @@ static const struct ivtv_card ivtv_card_cx23416gyc_nogrycs = {
        .gpio_audio_freq   = { .mask = 0xc000, .f32000 = 0x0000,
                             .f44100 = 0x4000, .f48000 = 0x8000 },
        .tuners = {
-               { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+               { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
                { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
        },
        .i2c = &ivtv_i2c_std,
@@ -667,7 +669,7 @@ static const struct ivtv_card ivtv_card_gv_mvprx = {
        .gpio_audio_input  = { .mask = 0xffff, .tuner  = 0x0200, .linein = 0x0300 },
        .tuners = {
                /* This card has the Panasonic VP27 tuner */
-               { .std = V4L2_STD_525_60, .tuner = TUNER_PANASONIC_VP27 },
+               { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PANASONIC_VP27 },
        },
        .pci_list = ivtv_pci_gv_mvprx,
        .i2c = &ivtv_i2c_std,
@@ -704,7 +706,7 @@ static const struct ivtv_card ivtv_card_gv_mvprx2e = {
        .gpio_audio_input  = { .mask = 0xffff, .tuner  = 0x0200, .linein = 0x0300 },
        .tuners = {
                /* This card has the Panasonic VP27 tuner */
-               { .std = V4L2_STD_525_60, .tuner = TUNER_PANASONIC_VP27 },
+               { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PANASONIC_VP27 },
        },
        .pci_list = ivtv_pci_gv_mvprx2e,
        .i2c = &ivtv_i2c_std,
@@ -739,7 +741,7 @@ static const struct ivtv_card ivtv_card_gotview_pci_dvd = {
        .gpio_init = { .direction = 0xf000, .initial_value = 0xA000 },
        .tuners = {
                /* This card has a Philips FQ1216ME MK3 tuner */
-               { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+               { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
        },
        .pci_list = ivtv_pci_gotview_pci_dvd,
        .i2c = &ivtv_i2c_std,
@@ -778,7 +780,7 @@ static const struct ivtv_card ivtv_card_gotview_pci_dvd2 = {
        .gpio_audio_input  = { .mask = 0x0800, .tuner = 0, .linein = 0, .radio = 0x0800 },
        .tuners = {
                /* This card has a Philips FQ1216ME MK5 tuner */
-               { .std = V4L2_STD_625_50, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+               { .std = V4L2_STD_NOT_MN, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
        },
        .pci_list = ivtv_pci_gotview_pci_dvd2,
        .i2c = &ivtv_i2c_std,
@@ -856,7 +858,7 @@ static const struct ivtv_card ivtv_card_dctmvtvp1 = {
        .gpio_video_input  = { .mask = 0x0030, .tuner  = 0x0000,
                               .composite = 0x0010, .svideo = 0x0020},
        .tuners = {
-               { .std = V4L2_STD_525_60, .tuner = TUNER_PHILIPS_FQ1286 },
+               { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
        },
        .pci_list = ivtv_pci_dctmvtvp1,
        .i2c = &ivtv_i2c_std,
@@ -875,6 +877,7 @@ static const struct ivtv_card_pci_info ivtv_pci_pg600v2[] = {
 static const struct ivtv_card ivtv_card_pg600v2 = {
        .type = IVTV_CARD_PG600V2,
        .name = "Yuan PG600-2, GotView PCI DVD Lite",
+       .comment = "only Composite and S-Video inputs are supported, not the tuner\n",
        .v4l2_capabilities = IVTV_CAP_ENCODER,
        .hw_video = IVTV_HW_CX25840,
        .hw_audio = IVTV_HW_CX25840,
@@ -921,6 +924,7 @@ static const struct ivtv_card ivtv_card_club3d = {
        },
        .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 },
        .gpio_init = { .direction = 0x1000, .initial_value = 0x1000 }, /* tuner reset */
+       .xceive_pin = 12,
        .tuners = {
                { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
        },
@@ -944,15 +948,22 @@ static const struct ivtv_card ivtv_card_avertv_mce116 = {
        .hw_video = IVTV_HW_CX25840,
        .hw_audio = IVTV_HW_CX25840,
        .hw_audio_ctrl = IVTV_HW_CX25840,
-       .hw_all = IVTV_HW_CX25840 | IVTV_HW_WM8739,
+       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | IVTV_HW_WM8739,
        .video_inputs = {
-               { IVTV_CARD_INPUT_SVIDEO1,    0, CX25840_SVIDEO3    },
-               { IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE1 },
+               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1, CX25840_SVIDEO3    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
        },
        .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5       },
                { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL, 1 },
        },
-       .gpio_init = { .direction = 0xe000, .initial_value = 0x4000 }, /* enable line-in */
+       /* enable line-in */
+       .gpio_init = { .direction = 0xe400, .initial_value = 0x4400 },
+       .xceive_pin = 10,
+       .tuners = {
+               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+       },
        .pci_list = ivtv_pci_avertv_mce116,
        .i2c = &ivtv_i2c_std,
 };
@@ -990,7 +1001,7 @@ static const struct ivtv_card ivtv_card_aver_pvr150 = {
        .gpio_audio_input  = { .mask = 0x0800, .tuner = 0, .linein = 0, .radio = 0x0800 },
        .tuners = {
                /* This card has a Partsnic PTI-5NF05 tuner */
-               { .std = V4L2_STD_525_60, .tuner = TUNER_TCL_2002N },
+               { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_TCL_2002N },
        },
        .pci_list = ivtv_pci_aver_pvr150,
        .i2c = &ivtv_i2c_radio,
@@ -1058,12 +1069,48 @@ static const struct ivtv_card ivtv_card_asus_falcon2 = {
        },
        .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, M52790_IN_TUNER },
        .tuners = {
-               { .std = V4L2_STD_525_60, .tuner = TUNER_PHILIPS_FM1236_MK3 },
+               { .std = V4L2_STD_525_60|V4L2_STD_MN, .tuner = TUNER_PHILIPS_FM1236_MK3 },
        },
        .pci_list = ivtv_pci_asus_falcon2,
        .i2c = &ivtv_i2c_std,
 };
 
+/* ------------------------------------------------------------------------- */
+
+/* AVerMedia M104 miniPCI card */
+
+static const struct ivtv_card_pci_info ivtv_pci_aver_m104[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc136 },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_aver_m104 = {
+       .type = IVTV_CARD_AVER_M104,
+       .name = "AVerMedia M104",
+       .comment = "Not yet supported!\n",
+       .v4l2_capabilities = 0, /*IVTV_CAP_ENCODER,*/
+       .hw_video = IVTV_HW_CX25840,
+       .hw_audio = IVTV_HW_CX25840,
+       .hw_audio_ctrl = IVTV_HW_CX25840,
+       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | IVTV_HW_WM8739,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_SVIDEO1,    0, CX25840_SVIDEO3    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE1 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL, 1 },
+       },
+       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 },
+       /* enable line-in + reset tuner */
+       .gpio_init = { .direction = 0xe400, .initial_value = 0x4000 },
+       .xceive_pin = 10,
+       .tuners = {
+               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+       },
+       .pci_list = ivtv_pci_aver_m104,
+       .i2c = &ivtv_i2c_std,
+};
+
 static const struct ivtv_card *ivtv_card_list[] = {
        &ivtv_card_pvr250,
        &ivtv_card_pvr350,
@@ -1089,6 +1136,7 @@ static const struct ivtv_card *ivtv_card_list[] = {
        &ivtv_card_asus_falcon2,
        &ivtv_card_aver_pvr150,
        &ivtv_card_aver_ezmaker,
+       &ivtv_card_aver_m104,
 
        /* Variations of standard cards but with the same PCI IDs.
           These cards must come last in this list. */
@@ -1120,7 +1168,8 @@ int ivtv_get_input(struct ivtv *itv, u16 index, struct v4l2_input *input)
        if (index >= itv->nof_inputs)
                return -EINVAL;
        input->index = index;
-       strcpy(input->name, input_strs[card_input->video_type - 1]);
+       strlcpy(input->name, input_strs[card_input->video_type - 1],
+                       sizeof(input->name));
        input->type = (card_input->video_type == IVTV_CARD_INPUT_VID_TUNER ?
                        V4L2_INPUT_TYPE_TUNER : V4L2_INPUT_TYPE_CAMERA);
        input->audioset = (1 << itv->nof_audio_inputs) - 1;
@@ -1137,7 +1186,7 @@ int ivtv_get_output(struct ivtv *itv, u16 index, struct v4l2_output *output)
        if (index >= itv->card->nof_outputs)
                return -EINVAL;
        output->index = index;
-       strcpy(output->name, card_output->name);
+       strlcpy(output->name, card_output->name, sizeof(output->name));
        output->type = V4L2_OUTPUT_TYPE_ANALOG;
        output->audioset = 1;
        output->std = V4L2_STD_ALL;
@@ -1156,7 +1205,8 @@ int ivtv_get_audio_input(struct ivtv *itv, u16 index, struct v4l2_audio *audio)
        memset(audio, 0, sizeof(*audio));
        if (index >= itv->nof_audio_inputs)
                return -EINVAL;
-       strcpy(audio->name, input_strs[aud_input->audio_type - 1]);
+       strlcpy(audio->name, input_strs[aud_input->audio_type - 1],
+                       sizeof(audio->name));
        audio->index = index;
        audio->capability = V4L2_AUDCAP_STEREO;
        return 0;
@@ -1167,6 +1217,6 @@ int ivtv_get_audio_output(struct ivtv *itv, u16 index, struct v4l2_audioout *aud
        memset(aud_output, 0, sizeof(*aud_output));
        if (itv->card->video_outputs == NULL || index != 0)
                return -EINVAL;
-       strcpy(aud_output->name, "A/V Audio Out");
+       strlcpy(aud_output->name, "A/V Audio Out", sizeof(aud_output->name));
        return 0;
 }
index 9186fa2ee5fc01bff46a451df77569cbe593eba6..748485dcebbdab220009e3ac05c307b9adbf2d71 100644 (file)
@@ -48,7 +48,8 @@
 #define IVTV_CARD_ASUS_FALCON2      21 /* ASUS Falcon2 */
 #define IVTV_CARD_AVER_PVR150PLUS    22 /* AVerMedia PVR-150 Plus */
 #define IVTV_CARD_AVER_EZMAKER       23 /* AVerMedia EZMaker PCI Deluxe */
-#define IVTV_CARD_LAST                      23
+#define IVTV_CARD_AVER_M104          24 /* AverMedia M104 miniPCI card */
+#define IVTV_CARD_LAST                      24
 
 /* Variants of existing cards but with the same PCI IDs. The driver
    detects these based on other device information.
@@ -244,6 +245,7 @@ struct ivtv_card_tuner_i2c {
 struct ivtv_card {
        int type;
        char *name;
+       char *comment;
        u32 v4l2_capabilities;
        u32 hw_video;           /* hardware used to process video */
        u32 hw_audio;           /* hardware used to process audio */
@@ -256,6 +258,7 @@ struct ivtv_card {
        int nof_outputs;
        const struct ivtv_card_output *video_outputs;
        u8 gr_config;           /* config byte for the ghost reduction device */
+       u8 xceive_pin;          /* XCeive tuner GPIO reset pin */
 
        /* GPIO card-specific settings */
        struct ivtv_gpio_init           gpio_init;
index 065df53f80fdcbf543486a9c1fb5ce739e440841..ed020f722b05ec840bada9ecdd776406c8ef18f1 100644 (file)
@@ -190,6 +190,7 @@ MODULE_PARM_DESC(cardtype,
                 "\t\t\t22 = ASUS Falcon2\n"
                 "\t\t\t23 = AverMedia PVR-150 Plus\n"
                 "\t\t\t24 = AverMedia EZMaker PCI Deluxe\n"
+                "\t\t\t25 = AverMedia M104 (not yet working)\n"
                 "\t\t\t 0 = Autodetect (default)\n"
                 "\t\t\t-1 = Ignore this card\n\t\t");
 MODULE_PARM_DESC(pal, "Set PAL standard: BGH, DK, I, M, N, Nc, 60");
@@ -871,7 +872,7 @@ static void ivtv_load_and_init_modules(struct ivtv *itv)
        unsigned i;
 
        /* load modules */
-#ifndef CONFIG_VIDEO_TUNER
+#ifndef CONFIG_MEDIA_TUNER
        hw = ivtv_request_module(itv, hw, "tuner", IVTV_HW_TUNER);
 #endif
 #ifndef CONFIG_VIDEO_CX25840
@@ -1048,7 +1049,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
                                       IVTV_ENCODER_SIZE);
        if (!itv->enc_mem) {
                IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n");
-               IVTV_ERR("or disabling CONFIG_HIMEM4G into the kernel would help\n");
+               IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n");
                retval = -ENOMEM;
                goto free_mem;
        }
@@ -1060,7 +1061,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
                                IVTV_DECODER_SIZE);
                if (!itv->dec_mem) {
                        IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n");
-                       IVTV_ERR("or disabling CONFIG_HIMEM4G into the kernel would help\n");
+                       IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n");
                        retval = -ENOMEM;
                        goto free_mem;
                }
@@ -1076,7 +1077,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
            ioremap_nocache(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
        if (!itv->reg_mem) {
                IVTV_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n");
-               IVTV_ERR("or disabling CONFIG_HIMEM4G into the kernel would help\n");
+               IVTV_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n");
                retval = -ENOMEM;
                goto free_io;
        }
@@ -1097,6 +1098,13 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
                   The PCI IDs are not always reliable. */
                ivtv_process_eeprom(itv);
        }
+       if (itv->card->comment)
+               IVTV_INFO("%s", itv->card->comment);
+       if (itv->card->v4l2_capabilities == 0) {
+               /* card was detected but is not supported */
+               retval = -ENODEV;
+               goto free_i2c;
+       }
 
        if (itv->std == 0) {
                itv->std = V4L2_STD_NTSC_M;
@@ -1195,13 +1203,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
                ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std);
        }
 
-       retval = ivtv_streams_setup(itv);
-       if (retval) {
-               IVTV_ERR("Error %d setting up streams\n", retval);
-               goto free_i2c;
-       }
-
-       IVTV_DEBUG_IRQ("Masking interrupts\n");
        /* clear interrupt mask, effectively disabling interrupts */
        ivtv_set_irq_mask(itv, 0xffffffff);
 
@@ -1210,32 +1211,38 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
                             IRQF_SHARED | IRQF_DISABLED, itv->name, (void *)itv);
        if (retval) {
                IVTV_ERR("Failed to register irq %d\n", retval);
-               goto free_streams;
+               goto free_i2c;
+       }
+
+       retval = ivtv_streams_setup(itv);
+       if (retval) {
+               IVTV_ERR("Error %d setting up streams\n", retval);
+               goto free_irq;
        }
        retval = ivtv_streams_register(itv);
        if (retval) {
                IVTV_ERR("Error %d registering devices\n", retval);
-               goto free_irq;
+               goto free_streams;
        }
        IVTV_INFO("Initialized card #%d: %s\n", itv->num, itv->card_name);
        return 0;
 
-      free_irq:
-       free_irq(itv->dev->irq, (void *)itv);
-      free_streams:
+free_streams:
        ivtv_streams_cleanup(itv);
-      free_i2c:
+free_irq:
+       free_irq(itv->dev->irq, (void *)itv);
+free_i2c:
        exit_ivtv_i2c(itv);
-      free_io:
+free_io:
        ivtv_iounmap(itv);
-      free_mem:
+free_mem:
        release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
        release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
        if (itv->has_cx23415)
                release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
-      free_workqueue:
+free_workqueue:
        destroy_workqueue(itv->irq_work_queues);
-      err:
+err:
        if (retval == 0)
                retval = -ENODEV;
        IVTV_ERR("Error %d on initialization\n", retval);
index a7640c49f1d84aa6f89e8f81e67b291d62a67350..2b74b0ab147788c7942d5af34dfe1beeb954f904 100644 (file)
@@ -755,8 +755,10 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait)
        IVTV_DEBUG_HI_FILE("Encoder poll\n");
        poll_wait(filp, &s->waitq, wait);
 
-       if (eof || s->q_full.length || s->q_io.length)
+       if (s->q_full.length || s->q_io.length)
                return POLLIN | POLLRDNORM;
+       if (eof)
+               return POLLHUP;
        return 0;
 }
 
index 688cd3856685f09a0374fa91f42f20efbf1fdc92..d8ac09f3cce6ffc17506c6bc7d7d4021e8bacf07 100644 (file)
@@ -128,20 +128,17 @@ int ivtv_reset_tuner_gpio(void *dev, int cmd, int value)
 {
        struct i2c_algo_bit_data *algo = dev;
        struct ivtv *itv = algo->data;
-       int curdir, curout;
+       u32 curout;
 
        if (cmd != XC2028_TUNER_RESET)
                return 0;
        IVTV_DEBUG_INFO("Resetting tuner\n");
        curout = read_reg(IVTV_REG_GPIO_OUT);
-       curdir = read_reg(IVTV_REG_GPIO_DIR);
-       curdir |= (1 << 12);  /* GPIO bit 12 */
-
-       curout &= ~(1 << 12);
+       curout &= ~(1 << itv->card->xceive_pin);
        write_reg(curout, IVTV_REG_GPIO_OUT);
        schedule_timeout_interruptible(msecs_to_jiffies(1));
 
-       curout |= (1 << 12);
+       curout |= 1 << itv->card->xceive_pin;
        write_reg(curout, IVTV_REG_GPIO_OUT);
        schedule_timeout_interruptible(msecs_to_jiffies(1));
        return 0;
index 9824eafee02131eb88b67045de9ce32de8f0e93e..771adf47e944ff1379f4264db37f4a17b4dc210b 100644 (file)
@@ -167,7 +167,8 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
                return -1;
        id = hw_driverids[idx];
        memset(&info, 0, sizeof(info));
-       strcpy(info.driver_name, hw_drivernames[idx]);
+       strlcpy(info.driver_name, hw_drivernames[idx],
+                       sizeof(info.driver_name));
        info.addr = hw_addrs[idx];
        for (i = 0; itv->i2c_clients[i] && i < I2C_CLIENTS_MAX; i++) {}
 
index 15cac1812122e22c11805e3fe006c5111f2581ae..d508b5d0538cfb71bfa9b7b2c137eebfcbdaafd4 100644 (file)
@@ -243,20 +243,31 @@ static int ivtv_validate_speed(int cur_speed, int new_speed)
        int fact = new_speed < 0 ? -1 : 1;
        int s;
 
-       if (new_speed < 0) new_speed = -new_speed;
-       if (cur_speed < 0) cur_speed = -cur_speed;
+       if (cur_speed == 0)
+               cur_speed = 1000;
+       if (new_speed < 0)
+               new_speed = -new_speed;
+       if (cur_speed < 0)
+               cur_speed = -cur_speed;
 
        if (cur_speed <= new_speed) {
-               if (new_speed > 1500) return fact * 2000;
-               if (new_speed > 1000) return fact * 1500;
+               if (new_speed > 1500)
+                       return fact * 2000;
+               if (new_speed > 1000)
+                       return fact * 1500;
        }
        else {
-               if (new_speed >= 2000) return fact * 2000;
-               if (new_speed >= 1500) return fact * 1500;
-               if (new_speed >= 1000) return fact * 1000;
-       }
-       if (new_speed == 0) return 1000;
-       if (new_speed == 1 || new_speed == 1000) return fact * new_speed;
+               if (new_speed >= 2000)
+                       return fact * 2000;
+               if (new_speed >= 1500)
+                       return fact * 1500;
+               if (new_speed >= 1000)
+                       return fact * 1000;
+       }
+       if (new_speed == 0)
+               return 1000;
+       if (new_speed == 1 || new_speed == 1000)
+               return fact * new_speed;
 
        s = new_speed;
        new_speed = 1000 / new_speed;
@@ -741,10 +752,9 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
                struct v4l2_capability *vcap = arg;
 
                memset(vcap, 0, sizeof(*vcap));
-               strcpy(vcap->driver, IVTV_DRIVER_NAME);     /* driver name */
-               strncpy(vcap->card, itv->card_name,
-                               sizeof(vcap->card)-1);      /* card type */
-               strcpy(vcap->bus_info, pci_name(itv->dev)); /* bus info... */
+               strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
+               strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
+               strlcpy(vcap->bus_info, pci_name(itv->dev), sizeof(vcap->bus_info));
                vcap->version = IVTV_DRIVER_VERSION;        /* version */
                vcap->capabilities = itv->v4l2_cap;         /* capabilities */
 
@@ -1018,7 +1028,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
                                ivtv_std_60hz : ivtv_std_50hz;
                vs->index = idx;
                vs->id = enum_stds[idx].std;
-               strcpy(vs->name, enum_stds[idx].name);
+               strlcpy(vs->name, enum_stds[idx].name, sizeof(vs->name));
                break;
        }
 
@@ -1102,10 +1112,10 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
                ivtv_call_i2c_clients(itv, VIDIOC_G_TUNER, vt);
 
                if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
-                       strcpy(vt->name, "ivtv Radio Tuner");
+                       strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));
                        vt->type = V4L2_TUNER_RADIO;
                } else {
-                       strcpy(vt->name, "ivtv TV Tuner");
+                       strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name));
                        vt->type = V4L2_TUNER_ANALOG_TV;
                }
                break;
index a329c4689dbf71de5b56a307c3256b6d8979aa76..d8ba3a4a8761fb0c66993ae5a2ae998aa068c58f 100644 (file)
@@ -384,7 +384,7 @@ static void ivtv_dma_enc_start_xfer(struct ivtv_stream *s)
        ivtv_stream_sync_for_device(s);
        write_reg(s->sg_handle, IVTV_REG_ENCDMAADDR);
        write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER);
-       itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
+       itv->dma_timer.expires = jiffies + msecs_to_jiffies(300);
        add_timer(&itv->dma_timer);
 }
 
@@ -400,7 +400,7 @@ static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s)
        ivtv_stream_sync_for_device(s);
        write_reg(s->sg_handle, IVTV_REG_DECDMAADDR);
        write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER);
-       itv->dma_timer.expires = jiffies + msecs_to_jiffies(100);
+       itv->dma_timer.expires = jiffies + msecs_to_jiffies(300);
        add_timer(&itv->dma_timer);
 }
 
index 0f1d4cc4b4d9b49dd95f2aa7b46411f0a9769fd9..02c5ab071d1b3518eec07500f78af9df25f0ea0f 100644 (file)
@@ -23,7 +23,7 @@
 #define IVTV_DRIVER_NAME "ivtv"
 #define IVTV_DRIVER_VERSION_MAJOR 1
 #define IVTV_DRIVER_VERSION_MINOR 2
-#define IVTV_DRIVER_VERSION_PATCHLEVEL 0
+#define IVTV_DRIVER_VERSION_PATCHLEVEL 1
 
 #define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL)
 #define IVTV_DRIVER_VERSION KERNEL_VERSION(IVTV_DRIVER_VERSION_MAJOR,IVTV_DRIVER_VERSION_MINOR,IVTV_DRIVER_VERSION_PATCHLEVEL)
index 3b23fc05f7c4331dc1d15b61af39a3cb1d3133da..df789f683e63ce1402f34725f0fe16ccb11e824a 100644 (file)
@@ -532,7 +532,7 @@ static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix)
 
        IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
        memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-       strcpy(fix->id, "cx23415 TV out");
+       strlcpy(fix->id, "cx23415 TV out", sizeof(fix->id));
        fix->smem_start = oi->video_pbase;
        fix->smem_len = oi->video_buffer_size;
        fix->type = FB_TYPE_PACKED_PIXELS;
index d4bf14c284ef2c967d59c3fe4b588d27170d0b49..5b9dfa2c51b43874e8b9045379ee685260982720 100644 (file)
@@ -126,7 +126,8 @@ static int m52790_command(struct i2c_client *client, unsigned int cmd,
 
 /* i2c implementation */
 
-static int m52790_probe(struct i2c_client *client)
+static int m52790_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
 {
        struct m52790_state *state;
 
index b73c740f7fb2697a5e128feee6de2f49abeec192..e6273162e12379e4ae054dfeb410458267f3c83a 100644 (file)
@@ -805,7 +805,7 @@ static int msp_resume(struct i2c_client *client)
 
 /* ----------------------------------------------------------------------- */
 
-static int msp_probe(struct i2c_client *client)
+static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
        struct msp_state *state;
        int (*thread_func)(void *data) = NULL;
index 3fb5f63df1e6392e000cd7e3b94180e5bec2705d..179e47049a452ff1619d977d4bc44779a1b00847 100644 (file)
@@ -372,7 +372,7 @@ static int mt9m001_set_register(struct soc_camera_device *icd,
 }
 #endif
 
-const struct v4l2_queryctrl mt9m001_controls[] = {
+static const struct v4l2_queryctrl mt9m001_controls[] = {
        {
                .id             = V4L2_CID_VFLIP,
                .type           = V4L2_CTRL_TYPE_BOOLEAN,
@@ -620,7 +620,8 @@ static void mt9m001_video_remove(struct soc_camera_device *icd)
        soc_camera_video_stop(&mt9m001->icd);
 }
 
-static int mt9m001_probe(struct i2c_client *client)
+static int mt9m001_probe(struct i2c_client *client,
+                        const struct i2c_device_id *did)
 {
        struct mt9m001 *mt9m001;
        struct soc_camera_device *icd;
@@ -696,12 +697,19 @@ static int mt9m001_remove(struct i2c_client *client)
        return 0;
 }
 
+static const struct i2c_device_id mt9m001_id[] = {
+       { "mt9m001", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, mt9m001_id);
+
 static struct i2c_driver mt9m001_i2c_driver = {
        .driver = {
                .name = "mt9m001",
        },
        .probe          = mt9m001_probe,
        .remove         = mt9m001_remove,
+       .id_table       = mt9m001_id,
 };
 
 static int __init mt9m001_mod_init(void)
index d4b9e2744343dd0dc7f48049deb2d61a9f6d0e2b..d1391ac550963b14ebeb2e52e9470c5215501bfd 100644 (file)
@@ -452,7 +452,7 @@ static int mt9v022_set_register(struct soc_camera_device *icd,
 }
 #endif
 
-const struct v4l2_queryctrl mt9v022_controls[] = {
+static const struct v4l2_queryctrl mt9v022_controls[] = {
        {
                .id             = V4L2_CID_VFLIP,
                .type           = V4L2_CTRL_TYPE_BOOLEAN,
@@ -745,7 +745,8 @@ static void mt9v022_video_remove(struct soc_camera_device *icd)
        soc_camera_video_stop(&mt9v022->icd);
 }
 
-static int mt9v022_probe(struct i2c_client *client)
+static int mt9v022_probe(struct i2c_client *client,
+                        const struct i2c_device_id *did)
 {
        struct mt9v022 *mt9v022;
        struct soc_camera_device *icd;
@@ -818,12 +819,19 @@ static int mt9v022_remove(struct i2c_client *client)
        return 0;
 }
 
+static const struct i2c_device_id mt9v022_id[] = {
+       { "mt9v022", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, mt9v022_id);
+
 static struct i2c_driver mt9v022_i2c_driver = {
        .driver = {
                .name = "mt9v022",
        },
        .probe          = mt9v022_probe,
        .remove         = mt9v022_remove,
+       .id_table       = mt9v022_id,
 };
 
 static int __init mt9v022_mod_init(void)
index 158b3d0c653282bf27ca31352be43a8a46ddf173..9620c67fae77050f442dd024f186915affda8353 100644 (file)
@@ -1,14 +1,15 @@
 config VIDEO_PVRUSB2
        tristate "Hauppauge WinTV-PVR USB2 support"
-       depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+       depends on VIDEO_V4L2 && I2C
        select FW_LOADER
-       select VIDEO_TUNER
+       select MEDIA_TUNER
        select VIDEO_TVEEPROM
        select VIDEO_CX2341X
        select VIDEO_SAA711X
        select VIDEO_CX25840
        select VIDEO_MSP3400
        select VIDEO_WM8775
+       select VIDEO_CS53L32A
        ---help---
          This is a video4linux driver for Conexant 23416 based
          usb2 personal video recorder devices.
@@ -16,32 +17,6 @@ config VIDEO_PVRUSB2
          To compile this driver as a module, choose M here: the
          module will be called pvrusb2
 
-config VIDEO_PVRUSB2_ONAIR_CREATOR
-       bool "pvrusb2 driver support for OnAir Creator model"
-       depends on VIDEO_PVRUSB2 && EXPERIMENTAL
-       select VIDEO_SAA711X
-       select VIDEO_CS53L32A
-       ---help---
-
-         This option enables support for the OnAir Creator USB tuner
-         device.  This is a hybrid device, however currently only
-         analog mode is supported.
-
-         If you are in doubt, say Y.
-
-config VIDEO_PVRUSB2_ONAIR_USB2
-       bool "pvrusb2 driver support for OnAir USB2 model"
-       depends on VIDEO_PVRUSB2 && EXPERIMENTAL
-       select VIDEO_SAA711X
-       select VIDEO_CS53L32A
-       ---help---
-
-         This option enables support for the OnAir USB2 tuner device
-         (also known as the Sasem tuner).  This is a hybrid device,
-         however currently only analog mode is supported.
-
-         If you are in doubt, say Y.
-
 config VIDEO_PVRUSB2_SYSFS
        bool "pvrusb2 sysfs support (EXPERIMENTAL)"
        default y
@@ -59,29 +34,23 @@ config VIDEO_PVRUSB2_SYSFS
          Note: This feature is experimental and subject to change.
 
 config VIDEO_PVRUSB2_DVB
-       bool "pvrusb2 DVB support (EXPERIMENTAL)"
-       default n
+       bool "pvrusb2 ATSC/DVB support (EXPERIMENTAL)"
+       default y
        depends on VIDEO_PVRUSB2 && DVB_CORE && EXPERIMENTAL
        select DVB_LGDT330X if !DVB_FE_CUSTOMISE
        select DVB_S5H1409 if !DVB_FE_CUSTOMISE
        select DVB_S5H1411 if !DVB_FE_CUSTOMISE
        select DVB_TDA10048 if !DVB_FE_CUSTOMIZE
-       select DVB_TDA18271 if !DVB_FE_CUSTOMIZE
-       select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
-       select TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
+       select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE
+       select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE
        ---help---
 
-         This option enables compilation of a DVB interface for the
-         pvrusb2 driver.  Currently this is very very experimental.
-         It is also limiting - the DVB interface can only access the
-         digital side of hybrid devices, and there are going to be
-         issues if you attempt to mess with the V4L side at the same
-         time.  Don't turn this on unless you know what you are
-         doing.
-
-         If you are in doubt, say N.
+         This option enables a DVB interface for the pvrusb2 driver.
+         If your device does not support digital television, this
+         feature will have no affect on the driver's operation.
 
-         Note: This feature is very experimental and might break
+         If you are in doubt, say Y.
 
 config VIDEO_PVRUSB2_DEBUGIFC
        bool "pvrusb2 debug interface"
index 5b3083c89aa9bcd1841c41d76c029d3ae682d4dc..4fda2de69ab7240022856bd4a2c3064b41c136d4 100644 (file)
@@ -16,5 +16,6 @@ pvrusb2-objs  := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
 obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o
 
 EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
index 11537ddf8aa3b0d6b81a44f069b83fb1feec220c..707d2d9635d7a9e2f68f8ecd5078f0b2e184f257 100644 (file)
@@ -54,6 +54,7 @@ extern int pvrusb2_debug;
 #define PVR2_TRACE_DATA_FLOW  (1 << 25) /* Track data flow */
 #define PVR2_TRACE_DEBUGIFC   (1 << 26) /* Debug interface actions */
 #define PVR2_TRACE_GPIO       (1 << 27) /* GPIO state bit changes */
+#define PVR2_TRACE_DVB_FEED   (1 << 28) /* DVB transport feed debug */
 
 
 #endif /* __PVRUSB2_HDW_INTERNAL_H */
index 3a141d93e1a9f2cff4792545bc697aedd5e60b29..5bf6d8fda1f9f284667093337b1ad851f09f9412 100644 (file)
@@ -153,7 +153,6 @@ static const struct pvr2_device_desc pvr2_device_gotview_2d = {
 
 
 
-#ifdef CONFIG_VIDEO_PVRUSB2_ONAIR_CREATOR
 /*------------------------------------------------------------------------*/
 /* OnAir Creator */
 
@@ -212,11 +211,9 @@ static const struct pvr2_device_desc pvr2_device_onair_creator = {
                .dvb_props = &pvr2_onair_creator_fe_props,
 #endif
 };
-#endif
 
 
 
-#ifdef CONFIG_VIDEO_PVRUSB2_ONAIR_USB2
 /*------------------------------------------------------------------------*/
 /* OnAir USB 2.0 */
 
@@ -274,7 +271,6 @@ static const struct pvr2_device_desc pvr2_device_onair_usb2 = {
                .dvb_props = &pvr2_onair_usb2_fe_props,
 #endif
 };
-#endif
 
 
 
@@ -497,14 +493,10 @@ struct usb_device_id pvr2_device_table[] = {
          .driver_info = (kernel_ulong_t)&pvr2_device_gotview_2},
        { USB_DEVICE(0x1164, 0x0602),
          .driver_info = (kernel_ulong_t)&pvr2_device_gotview_2d},
-#ifdef CONFIG_VIDEO_PVRUSB2_ONAIR_CREATOR
        { USB_DEVICE(0x11ba, 0x1003),
          .driver_info = (kernel_ulong_t)&pvr2_device_onair_creator},
-#endif
-#ifdef CONFIG_VIDEO_PVRUSB2_ONAIR_USB2
        { USB_DEVICE(0x11ba, 0x1001),
          .driver_info = (kernel_ulong_t)&pvr2_device_onair_usb2},
-#endif
        { USB_DEVICE(0x2040, 0x7300),
          .driver_info = (kernel_ulong_t)&pvr2_device_73xxx},
        { USB_DEVICE(0x2040, 0x7500),
index 6504c97e0bbcc299e7a16380144eeb92be5da6d3..6ec4bf81fc7f3e0d65c2f3308e0ae93fdff0aa82 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 #include "dvbdev.h"
+#include "pvrusb2-debug.h"
 #include "pvrusb2-hdw-internal.h"
 #include "pvrusb2-hdw.h"
 #include "pvrusb2-io.h"
@@ -35,7 +36,7 @@ static int pvr2_dvb_feed_func(struct pvr2_dvb_adapter *adap)
        struct pvr2_buffer *bp;
        struct pvr2_stream *stream;
 
-       printk(KERN_DEBUG "dvb thread started\n");
+       pvr2_trace(PVR2_TRACE_DVB_FEED, "dvb feed thread started");
        set_freezable();
 
        stream = adap->channel.stream->stream;
@@ -82,7 +83,7 @@ static int pvr2_dvb_feed_func(struct pvr2_dvb_adapter *adap)
        /* If we get here and ret is < 0, then an error has occurred.
           Probably would be a good idea to communicate that to DVB core... */
 
-       printk(KERN_DEBUG "dvb thread stopped\n");
+       pvr2_trace(PVR2_TRACE_DVB_FEED, "dvb feed thread stopped");
 
        return 0;
 }
@@ -210,7 +211,8 @@ static int pvr2_dvb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
        do {
                if (onoff) {
                        if (!adap->feedcount) {
-                               printk(KERN_DEBUG "start feeding\n");
+                               pvr2_trace(PVR2_TRACE_DVB_FEED,
+                                          "start feeding demux");
                                ret = pvr2_dvb_stream_start(adap);
                                if (ret < 0) break;
                        }
@@ -218,7 +220,8 @@ static int pvr2_dvb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
                } else if (adap->feedcount > 0) {
                        (adap->feedcount)--;
                        if (!adap->feedcount) {
-                               printk(KERN_DEBUG "stop feeding\n");
+                               pvr2_trace(PVR2_TRACE_DVB_FEED,
+                                          "stop feeding demux");
                                pvr2_dvb_stream_end(adap);
                        }
                }
@@ -230,15 +233,13 @@ static int pvr2_dvb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
 
 static int pvr2_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
-       printk(KERN_DEBUG "start pid: 0x%04x, feedtype: %d\n",
-              dvbdmxfeed->pid, dvbdmxfeed->type);
+       pvr2_trace(PVR2_TRACE_DVB_FEED, "start pid: 0x%04x", dvbdmxfeed->pid);
        return pvr2_dvb_ctrl_feed(dvbdmxfeed, 1);
 }
 
 static int pvr2_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
-       printk(KERN_DEBUG "stop pid: 0x%04x, feedtype: %d\n",
-              dvbdmxfeed->pid, dvbdmxfeed->type);
+       pvr2_trace(PVR2_TRACE_DVB_FEED, "stop pid: 0x%04x", dvbdmxfeed->pid);
        return pvr2_dvb_ctrl_feed(dvbdmxfeed, 0);
 }
 
@@ -259,7 +260,8 @@ static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap)
                                   &adap->channel.hdw->usb_dev->dev,
                                   adapter_nr);
        if (ret < 0) {
-               err("dvb_register_adapter failed: error %d", ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "dvb_register_adapter failed: error %d", ret);
                goto err;
        }
        adap->dvb_adap.priv = adap;
@@ -276,7 +278,8 @@ static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap)
 
        ret = dvb_dmx_init(&adap->demux);
        if (ret < 0) {
-               err("dvb_dmx_init failed: error %d", ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "dvb_dmx_init failed: error %d", ret);
                goto err_dmx;
        }
 
@@ -286,7 +289,8 @@ static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap)
 
        ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap);
        if (ret < 0) {
-               err("dvb_dmxdev_init failed: error %d", ret);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "dvb_dmxdev_init failed: error %d", ret);
                goto err_dmx_dev;
        }
 
@@ -304,7 +308,7 @@ err:
 
 static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap)
 {
-       printk(KERN_DEBUG "unregistering DVB devices\n");
+       pvr2_trace(PVR2_TRACE_INFO, "unregistering DVB devices");
        dvb_net_release(&adap->dvb_net);
        adap->demux.dmx.close(&adap->demux.dmx);
        dvb_dmxdev_release(&adap->dmxdev);
@@ -320,7 +324,7 @@ static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
        int ret = 0;
 
        if (dvb_props == NULL) {
-               err("fe_props not defined!");
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS, "fe_props not defined!");
                return -EINVAL;
        }
 
@@ -328,13 +332,15 @@ static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
            &adap->channel,
            (1 << PVR2_CVAL_INPUT_DTV));
        if (ret) {
-               err("failed to grab control of dtv input (code=%d)",
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "failed to grab control of dtv input (code=%d)",
                    ret);
                return ret;
        }
 
        if (dvb_props->frontend_attach == NULL) {
-               err("frontend_attach not defined!");
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "frontend_attach not defined!");
                ret = -EINVAL;
                goto done;
        }
@@ -342,7 +348,8 @@ static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
        if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) {
 
                if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
-                       err("frontend registration failed!");
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "frontend registration failed!");
                        dvb_frontend_detach(adap->fe);
                        adap->fe = NULL;
                        ret = -ENODEV;
@@ -359,7 +366,8 @@ static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
                adap->fe->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl;
 
        } else {
-               err("no frontend was attached!");
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "no frontend was attached!");
                ret = -ENODEV;
                return ret;
        }
index 416d05d4a969088d02d2f1c5a319de4fb215fe68..e684108637add93351b42fb005f27cc9da5be7da 100644 (file)
@@ -1450,7 +1450,8 @@ static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *ar
 
 /* ----------------------------------------------------------------------- */
 
-static int saa7115_probe(struct i2c_client *client)
+static int saa7115_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
 {
        struct saa711x_state *state;
        int     i;
index 06c88db656b41d4a8a94dc67ef9814c4fe852e50..e750cd65c1c37676612c1955c9674ad5b232ebb5 100644 (file)
@@ -661,7 +661,8 @@ static int saa7127_command(struct i2c_client *client,
 
 /* ----------------------------------------------------------------------- */
 
-static int saa7127_probe(struct i2c_client *client)
+static int saa7127_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
 {
        struct saa7127_state *state;
        struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 };  /* set to disabled */
index e086f14d56639ef458e1c69be6dd83eaa7d50f57..40e4c3bd2cb9b39a6b764793f3286801454e508c 100644 (file)
@@ -3,7 +3,7 @@ config VIDEO_SAA7134
        depends on VIDEO_DEV && PCI && I2C && INPUT
        select VIDEOBUF_DMA_SG
        select VIDEO_IR
-       select VIDEO_TUNER
+       select MEDIA_TUNER
        select VIDEO_TVEEPROM
        select CRC32
        ---help---
@@ -35,9 +35,9 @@ config VIDEO_SAA7134_DVB
        select DVB_NXT200X if !DVB_FE_CUSTOMISE
        select DVB_TDA10086 if !DVB_FE_CUSTOMISE
        select DVB_TDA826X if !DVB_FE_CUSTOMISE
-       select DVB_TDA827X if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE
        select DVB_ISL6421 if !DVB_FE_CUSTOMISE
-       select TUNER_SIMPLE if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE
        ---help---
          This adds support for DVB cards based on the
          Philips saa7134 chip.
index 9aff937ba7a5232ab506d8f1e0617f5089be3726..3dbaa19a6d00d7f3dbc81f7769681c91d5fff41e 100644 (file)
@@ -11,5 +11,6 @@ obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o
 obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o
 
 EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
index 98375955a84b7c42e62b34a83cf76dc358d0c52f..b111903aa322cd287a4d5ca0041396242b7e6c43 100644 (file)
@@ -47,6 +47,9 @@ static char name_svideo[]  = "S-Video";
 /* ------------------------------------------------------------------ */
 /* board config info                                                  */
 
+/* If radio_type !=UNSET, radio_addr should be specified
+ */
+
 struct saa7134_board saa7134_boards[] = {
        [SAA7134_BOARD_UNKNOWN] = {
                .name           = "UNKNOWN/GENERIC",
@@ -3087,7 +3090,7 @@ struct saa7134_board saa7134_boards[] = {
                .tuner_type     = TUNER_PHILIPS_TD1316, /* untested */
                .radio_type     = TUNER_TEA5767, /* untested */
                .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
+               .radio_addr     = 0x60,
                .tda9887_conf   = TDA9887_PRESENT,
                .mpeg           = SAA7134_MPEG_DVB,
                .inputs         = {{
@@ -4247,6 +4250,36 @@ struct saa7134_board saa7134_boards[] = {
                        .amux = LINE1,
                } },
        },
+       [SAA7134_BOARD_BEHOLD_H6] = {
+               /* Igor Kuznetsov <igk@igk.ru> */
+               .name           = "Beholder BeholdTV H6",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+               /* no DVB support for now */
+               /* .mpeg           = SAA7134_MPEG_DVB, */
+       },
 };
 
 const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -5197,6 +5230,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .subvendor    = 0x5ace,
                .subdevice    = 0x6193,
                .driver_data  = SAA7134_BOARD_BEHOLD_M6,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5ace,
+               .subdevice    = 0x6191,
+               .driver_data  = SAA7134_BOARD_BEHOLD_M6,
        },{
                .vendor       = PCI_VENDOR_ID_PHILIPS,
                .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
@@ -5245,6 +5284,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .subvendor    = 0x185b,
                .subdevice    = 0xc900,
                .driver_data  = SAA7134_BOARD_VIDEOMATE_T750,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5ace,
+               .subdevice    = 0x6290,
+               .driver_data  = SAA7134_BOARD_BEHOLD_H6,
        }, {
                /* --- boards without eeprom + subsystem ID --- */
                .vendor       = PCI_VENDOR_ID_PHILIPS,
@@ -5577,20 +5622,87 @@ int saa7134_board_init1(struct saa7134_dev *dev)
        return 0;
 }
 
+static void saa7134_tuner_setup(struct saa7134_dev *dev)
+{
+       struct tuner_setup tun_setup;
+       unsigned int mode_mask = T_RADIO     |
+                                T_ANALOG_TV |
+                                T_DIGITAL_TV;
+
+       memset(&tun_setup, 0, sizeof(tun_setup));
+       tun_setup.tuner_callback = saa7134_tuner_callback;
+
+       if (saa7134_boards[dev->board].radio_type != UNSET) {
+               tun_setup.type = saa7134_boards[dev->board].radio_type;
+               tun_setup.addr = saa7134_boards[dev->board].radio_addr;
+
+               tun_setup.mode_mask = T_RADIO;
+
+               saa7134_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
+               mode_mask &= ~T_RADIO;
+       }
+
+       if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type != UNSET)) {
+               tun_setup.type = dev->tuner_type;
+               tun_setup.addr = dev->tuner_addr;
+               tun_setup.config = saa7134_boards[dev->board].tuner_config;
+               tun_setup.tuner_callback = saa7134_tuner_callback;
+
+               tun_setup.mode_mask = mode_mask;
+
+               saa7134_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
+       }
+
+       if (dev->tda9887_conf) {
+               struct v4l2_priv_tun_config tda9887_cfg;
+
+               tda9887_cfg.tuner = TUNER_TDA9887;
+               tda9887_cfg.priv = &dev->tda9887_conf;
+
+               saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG,
+                                        &tda9887_cfg);
+       }
+
+       if (dev->tuner_type == TUNER_XC2028) {
+               struct v4l2_priv_tun_config  xc2028_cfg;
+               struct xc2028_ctrl           ctl;
+
+               memset(&xc2028_cfg, 0, sizeof(ctl));
+               memset(&ctl, 0, sizeof(ctl));
+
+               ctl.fname   = XC2028_DEFAULT_FIRMWARE;
+               ctl.max_len = 64;
+
+               switch (dev->board) {
+               case SAA7134_BOARD_AVERMEDIA_A16D:
+                       ctl.demod = XC3028_FE_ZARLINK456;
+                       break;
+               default:
+                       ctl.demod = XC3028_FE_OREN538;
+                       ctl.mts = 1;
+               }
+
+               xc2028_cfg.tuner = TUNER_XC2028;
+               xc2028_cfg.priv  = &ctl;
+
+               saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg);
+       }
+}
+
 /* stuff which needs working i2c */
 int saa7134_board_init2(struct saa7134_dev *dev)
 {
        unsigned char buf;
        int board;
-       struct tuner_setup tun_setup;
-       tun_setup.config = 0;
-       tun_setup.tuner_callback = saa7134_tuner_callback;
+
+       dev->tuner_type = saa7134_boards[dev->board].tuner_type;
+       dev->tuner_addr = saa7134_boards[dev->board].tuner_addr;
 
        switch (dev->board) {
        case SAA7134_BOARD_BMK_MPEX_NOTUNER:
        case SAA7134_BOARD_BMK_MPEX_TUNER:
                dev->i2c_client.addr = 0x60;
-               board = (i2c_master_recv(&dev->i2c_client,&buf,0) < 0)
+               board = (i2c_master_recv(&dev->i2c_client, &buf, 0) < 0)
                        ? SAA7134_BOARD_BMK_MPEX_NOTUNER
                        : SAA7134_BOARD_BMK_MPEX_TUNER;
                if (board == dev->board)
@@ -5600,21 +5712,9 @@ int saa7134_board_init2(struct saa7134_dev *dev)
                saa7134_boards[dev->board].name);
                dev->tuner_type = saa7134_boards[dev->board].tuner_type;
 
-               if (TUNER_ABSENT != dev->tuner_type) {
-                       tun_setup.mode_mask = T_RADIO     |
-                                             T_ANALOG_TV |
-                                             T_DIGITAL_TV;
-                       tun_setup.type = dev->tuner_type;
-                       tun_setup.addr = ADDR_UNSET;
-                       tun_setup.tuner_callback = saa7134_tuner_callback;
-
-                       saa7134_i2c_call_clients(dev,
-                                                TUNER_SET_TYPE_ADDR,
-                                                &tun_setup);
-               }
                break;
        case SAA7134_BOARD_MD7134:
-               {
+       {
                u8 subaddr;
                u8 data[3];
                int ret, tuner_t;
@@ -5667,30 +5767,8 @@ int saa7134_board_init2(struct saa7134_dev *dev)
                }
 
                printk(KERN_INFO "%s Tuner type is %d\n", dev->name, dev->tuner_type);
-               if (dev->tuner_type == TUNER_PHILIPS_FMD1216ME_MK3) {
-                       struct v4l2_priv_tun_config tda9887_cfg;
-
-                       tda9887_cfg.tuner = TUNER_TDA9887;
-                       tda9887_cfg.priv  = &dev->tda9887_conf;
-
-                       dev->tda9887_conf = TDA9887_PRESENT      |
-                                           TDA9887_PORT1_ACTIVE |
-                                           TDA9887_PORT2_ACTIVE;
-
-                       saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG,
-                                                &tda9887_cfg);
-               }
-
-               tun_setup.mode_mask = T_RADIO     |
-                                     T_ANALOG_TV |
-                                     T_DIGITAL_TV;
-               tun_setup.type = dev->tuner_type;
-               tun_setup.addr = ADDR_UNSET;
-
-               saa7134_i2c_call_clients(dev,
-                                        TUNER_SET_TYPE_ADDR, &tun_setup);
-               }
                break;
+       }
        case SAA7134_BOARD_PHILIPS_EUROPA:
                if (dev->autodetected && (dev->eedata[0x41] == 0x1c)) {
                        /* Reconfigure board as Snake reference design */
@@ -5702,43 +5780,43 @@ int saa7134_board_init2(struct saa7134_dev *dev)
                }
        case SAA7134_BOARD_VIDEOMATE_DVBT_300:
        case SAA7134_BOARD_ASUS_EUROPA2_HYBRID:
+       {
+
                /* The Philips EUROPA based hybrid boards have the tuner connected through
                 * the channel decoder. We have to make it transparent to find it
                 */
-               {
                u8 data[] = { 0x07, 0x02};
                struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
                i2c_transfer(&dev->i2c_adap, &msg, 1);
 
-               tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
-               tun_setup.type = dev->tuner_type;
-               tun_setup.addr = dev->tuner_addr;
-
-               saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup);
-               }
                break;
+       }
        case SAA7134_BOARD_PHILIPS_TIGER:
        case SAA7134_BOARD_PHILIPS_TIGER_S:
-               {
+       {
                u8 data[] = { 0x3c, 0x33, 0x60};
                struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
-               if(dev->autodetected && (dev->eedata[0x49] == 0x50)) {
+               if (dev->autodetected && (dev->eedata[0x49] == 0x50)) {
                        dev->board = SAA7134_BOARD_PHILIPS_TIGER_S;
                        printk(KERN_INFO "%s: Reconfigured board as %s\n",
                                dev->name, saa7134_boards[dev->board].name);
                }
-               if(dev->board == SAA7134_BOARD_PHILIPS_TIGER_S) {
-                       tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
-                       tun_setup.type = TUNER_PHILIPS_TDA8290;
-                       tun_setup.addr = 0x4b;
-                       tun_setup.config = 2;
+               if (dev->board == SAA7134_BOARD_PHILIPS_TIGER_S) {
+                       dev->tuner_type = TUNER_PHILIPS_TDA8290;
+
+                       saa7134_tuner_setup(dev);
 
-                       saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup);
                        data[2] = 0x68;
+                       i2c_transfer(&dev->i2c_adap, &msg, 1);
+
+                       /* Tuner setup is handled before I2C transfer.
+                          Due to that, there's no need to do it later
+                        */
+                       return 0;
                }
                i2c_transfer(&dev->i2c_adap, &msg, 1);
-               }
                break;
+       }
        case SAA7134_BOARD_HAUPPAUGE_HVR1110:
                hauppauge_eeprom(dev, dev->eedata+0x80);
                /* break intentionally omitted */
@@ -5751,52 +5829,55 @@ int saa7134_board_init2(struct saa7134_dev *dev)
        case SAA7134_BOARD_AVERMEDIA_SUPER_007:
        case SAA7134_BOARD_TWINHAN_DTV_DVB_3056:
        case SAA7134_BOARD_CREATIX_CTX953:
+       {
                /* this is a hybrid board, initialize to analog mode
                 * and configure firmware eeprom address
                 */
-               {
                u8 data[] = { 0x3c, 0x33, 0x60};
                struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
                i2c_transfer(&dev->i2c_adap, &msg, 1);
-               }
                break;
+       }
        case SAA7134_BOARD_FLYDVB_TRIO:
-               {
+       {
                u8 data[] = { 0x3c, 0x33, 0x62};
                struct i2c_msg msg = {.addr=0x09, .flags=0, .buf=data, .len = sizeof(data)};
                i2c_transfer(&dev->i2c_adap, &msg, 1);
-               }
                break;
+       }
        case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
        case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
+       {
                /* initialize analog mode  */
-               {
                u8 data[] = { 0x3c, 0x33, 0x6a};
                struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
                i2c_transfer(&dev->i2c_adap, &msg, 1);
-               }
                break;
+       }
        case SAA7134_BOARD_CINERGY_HT_PCMCIA:
        case SAA7134_BOARD_CINERGY_HT_PCI:
+       {
                /* initialize analog mode */
-               {
                u8 data[] = { 0x3c, 0x33, 0x68};
                struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
                i2c_transfer(&dev->i2c_adap, &msg, 1);
-               }
                break;
+       }
        case SAA7134_BOARD_KWORLD_ATSC110:
-               {
-                       /* enable tuner */
-                       int i;
-                       static const u8 buffer [] = { 0x10,0x12,0x13,0x04,0x16,0x00,0x14,0x04,0x017,0x00 };
-                       dev->i2c_client.addr = 0x0a;
-                       for (i = 0; i < 5; i++)
-                               if (2 != i2c_master_send(&dev->i2c_client,&buffer[i*2],2))
-                                       printk(KERN_WARNING "%s: Unable to enable tuner(%i).\n",
-                                              dev->name, i);
-               }
+       {
+               /* enable tuner */
+               int i;
+               static const u8 buffer [] = { 0x10, 0x12, 0x13, 0x04, 0x16,
+                                             0x00, 0x14, 0x04, 0x17, 0x00 };
+               dev->i2c_client.addr = 0x0a;
+               for (i = 0; i < 5; i++)
+                       if (2 != i2c_master_send(&dev->i2c_client,
+                                                &buffer[i*2], 2))
+                               printk(KERN_WARNING
+                                      "%s: Unable to enable tuner(%i).\n",
+                                      dev->name, i);
                break;
+       }
        case SAA7134_BOARD_VIDEOMATE_DVBT_200:
        case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
                /* The T200 and the T200A share the same pci id.  Consequently,
@@ -5821,7 +5902,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
                }
                break;
        case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
-               {
+       {
                struct v4l2_priv_tun_config tea5767_cfg;
                struct tea5767_ctrl ctl;
 
@@ -5832,34 +5913,11 @@ int saa7134_board_init2(struct saa7134_dev *dev)
                tea5767_cfg.tuner = TUNER_TEA5767;
                tea5767_cfg.priv  = &ctl;
                saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tea5767_cfg);
-               }
                break;
        }
+       } /* switch() */
 
-       if (dev->tuner_type == TUNER_XC2028) {
-               struct v4l2_priv_tun_config  xc2028_cfg;
-               struct xc2028_ctrl           ctl;
-
-               memset(&xc2028_cfg, 0, sizeof(ctl));
-               memset(&ctl, 0, sizeof(ctl));
-
-               ctl.fname   = XC2028_DEFAULT_FIRMWARE;
-               ctl.max_len = 64;
-
-               switch (dev->board) {
-               case SAA7134_BOARD_AVERMEDIA_A16D:
-                       ctl.demod = XC3028_FE_ZARLINK456;
-                       break;
-               default:
-                       ctl.demod = XC3028_FE_OREN538;
-                       ctl.mts = 1;
-               }
-
-               xc2028_cfg.tuner = TUNER_XC2028;
-               xc2028_cfg.priv  = &ctl;
-
-               saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg);
-       }
+       saa7134_tuner_setup(dev);
 
        return 0;
 }
index 2ccfaba0c490bfc6d42da43722a8ab6f665d42c9..d8af3863f2d3de675492e34d8a84ec2269d1e5ff 100644 (file)
@@ -324,8 +324,6 @@ static u32 functionality(struct i2c_adapter *adap)
 static int attach_inform(struct i2c_client *client)
 {
        struct saa7134_dev *dev = client->adapter->algo_data;
-       int tuner = dev->tuner_type;
-       struct tuner_setup tun_setup;
 
        d1printk( "%s i2c attach [addr=0x%x,client=%s]\n",
                client->driver->driver.name, client->addr, client->name);
@@ -346,46 +344,6 @@ static int attach_inform(struct i2c_client *client)
                }
        }
 
-       if (!client->driver->command)
-               return 0;
-
-       if (saa7134_boards[dev->board].radio_type != UNSET) {
-
-               tun_setup.type = saa7134_boards[dev->board].radio_type;
-               tun_setup.addr = saa7134_boards[dev->board].radio_addr;
-
-               if ((tun_setup.addr == ADDR_UNSET) || (tun_setup.addr == client->addr)) {
-                       tun_setup.mode_mask = T_RADIO;
-
-                       client->driver->command(client, TUNER_SET_TYPE_ADDR, &tun_setup);
-               }
-       }
-
-       if (tuner != UNSET) {
-               tun_setup.type = tuner;
-               tun_setup.addr = saa7134_boards[dev->board].tuner_addr;
-               tun_setup.config = saa7134_boards[dev->board].tuner_config;
-               tun_setup.tuner_callback = saa7134_tuner_callback;
-
-               if ((tun_setup.addr == ADDR_UNSET)||(tun_setup.addr == client->addr)) {
-
-                       tun_setup.mode_mask = T_ANALOG_TV;
-
-                       client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_setup);
-               }
-
-               if (tuner == TUNER_TDA9887) {
-                       struct v4l2_priv_tun_config tda9887_cfg;
-
-                       tda9887_cfg.tuner = TUNER_TDA9887;
-                       tda9887_cfg.priv = &dev->tda9887_conf;
-
-                       client->driver->command(client, TUNER_SET_CONFIG,
-                                               &tda9887_cfg);
-               }
-       }
-
-
        return 0;
 }
 
index 767ff30832f27d9e613ca3883c9f174438a59064..919632b10aae0ed20510fc68c2d89e944117b00c 100644 (file)
@@ -531,6 +531,7 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir)
                break;
        case SAA7134_BOARD_BEHOLD_607_9FM:
        case SAA7134_BOARD_BEHOLD_M6:
+       case SAA7134_BOARD_BEHOLD_H6:
                snprintf(ir->c.name, sizeof(ir->c.name), "BeholdTV");
                ir->get_key   = get_key_beholdm6xx;
                ir->ir_codes  = ir_codes_behold;
index 924ffd13637ead8b5e66d058b037ae7b9cbb9bd1..34ff0d4998f382ea53e68cae6e4c22a787b76b1a 100644 (file)
@@ -263,6 +263,7 @@ struct saa7134_format {
 #define SAA7134_BOARD_VIDEOMATE_T750       139
 #define SAA7134_BOARD_AVERMEDIA_A700_PRO    140
 #define SAA7134_BOARD_AVERMEDIA_A700_HYBRID 141
+#define SAA7134_BOARD_BEHOLD_H6      142
 
 
 #define SAA7134_MAXBOARDS 8
index 53c5edbcf7ea1add2ce7ea1730ef0fd0332df3c3..72c4081feff5e4d8af049bacbc5d62ab07181b3b 100644 (file)
@@ -1418,7 +1418,8 @@ static int saa717x_command(struct i2c_client *client, unsigned cmd, void *arg)
 /* i2c implementation */
 
 /* ----------------------------------------------------------------------- */
-static int saa717x_probe(struct i2c_client *client)
+static int saa717x_probe(struct i2c_client *client,
+                        const struct i2c_device_id *did)
 {
        struct saa717x_state *decoder;
        u8 id = 0;
index 6943b447a1bd7f4067e4a6f97a92c9e6d67ef83e..e57a646057785eb51dd331febc4db1772284204c 100644 (file)
@@ -840,7 +840,8 @@ static struct v4l2_int_device tcm825x_int_device = {
        },
 };
 
-static int tcm825x_probe(struct i2c_client *client)
+static int tcm825x_probe(struct i2c_client *client,
+                        const struct i2c_device_id *did)
 {
        struct tcm825x_sensor *sensor = &tcm825x;
        int rval;
index dc7b9c220b90f5f7ab3e25b18dd00c571daa912f..f1db54202deaebb36138b119279bdf18424644aa 100644 (file)
@@ -125,7 +125,8 @@ static int tlv320aic23b_command(struct i2c_client *client,
  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  */
 
-static int tlv320aic23b_probe(struct i2c_client *client)
+static int tlv320aic23b_probe(struct i2c_client *client,
+                             const struct i2c_device_id *id)
 {
        struct tlv320aic23b_state *state;
 
index 2b72e10e6b9f3274c1f6408f0625fc437706a10d..6bf104ea051da24c06c8b7d7bfe470555bd2f964 100644 (file)
 
 #define PREFIX t->i2c->driver->driver.name
 
+/** This macro allows us to probe dynamically, avoiding static links */
+#ifdef CONFIG_MEDIA_ATTACH
+#define tuner_symbol_probe(FUNCTION, ARGS...) ({ \
+       int __r = -EINVAL; \
+       typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
+       if (__a) { \
+               __r = (int) __a(ARGS); \
+       } else { \
+               printk(KERN_ERR "TUNER: Unable to find " \
+                               "symbol "#FUNCTION"()\n"); \
+       } \
+       symbol_put(FUNCTION); \
+       __r; \
+})
+
+static void tuner_detach(struct dvb_frontend *fe)
+{
+       if (fe->ops.tuner_ops.release) {
+               fe->ops.tuner_ops.release(fe);
+               symbol_put_addr(fe->ops.tuner_ops.release);
+       }
+       if (fe->ops.analog_ops.release) {
+               fe->ops.analog_ops.release(fe);
+               symbol_put_addr(fe->ops.analog_ops.release);
+       }
+}
+#else
+#define tuner_symbol_probe(FUNCTION, ARGS...) ({ \
+       FUNCTION(ARGS); \
+})
+
+static void tuner_detach(struct dvb_frontend *fe)
+{
+       if (fe->ops.tuner_ops.release)
+               fe->ops.tuner_ops.release(fe);
+       if (fe->ops.analog_ops.release)
+               fe->ops.analog_ops.release(fe);
+}
+#endif
+
 struct tuner {
        /* device */
        struct dvb_frontend fe;
@@ -56,7 +96,7 @@ struct tuner {
 
 /* standard i2c insmod options */
 static unsigned short normal_i2c[] = {
-#if defined(CONFIG_TUNER_TEA5761) || (defined(CONFIG_TUNER_TEA5761_MODULE) && defined(MODULE))
+#if defined(CONFIG_MEDIA_TUNER_TEA5761) || (defined(CONFIG_MEDIA_TUNER_TEA5761_MODULE) && defined(MODULE))
        0x10,
 #endif
        0x42, 0x43, 0x4a, 0x4b,                 /* tda8290 */
@@ -139,22 +179,6 @@ static void fe_set_params(struct dvb_frontend *fe,
        fe_tuner_ops->set_analog_params(fe, params);
 }
 
-static void fe_release(struct dvb_frontend *fe)
-{
-       if (fe->ops.tuner_ops.release)
-               fe->ops.tuner_ops.release(fe);
-
-       /* DO NOT kfree(fe->analog_demod_priv)
-        *
-        * If we are in this function, analog_demod_priv contains a pointer
-        * to struct tuner *t.  This will be kfree'd in tuner_detach().
-        *
-        * Otherwise, fe->ops.analog_demod_ops->release will
-        * handle the cleanup for analog demodulator modules.
-        */
-       fe->analog_demod_priv = NULL;
-}
-
 static void fe_standby(struct dvb_frontend *fe)
 {
        struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
@@ -191,7 +215,6 @@ static void tuner_status(struct dvb_frontend *fe);
 static struct analog_demod_ops tuner_core_ops = {
        .set_params     = fe_set_params,
        .standby        = fe_standby,
-       .release        = fe_release,
        .has_signal     = fe_has_signal,
        .set_config     = fe_set_config,
        .tuner_status   = tuner_status
@@ -323,7 +346,8 @@ static void attach_tda829x(struct tuner *t)
                .lna_cfg        = t->config,
                .tuner_callback = t->tuner_callback,
        };
-       tda829x_attach(&t->fe, t->i2c->adapter, t->i2c->addr, &cfg);
+       dvb_attach(tda829x_attach,
+                  &t->fe, t->i2c->adapter, t->i2c->addr, &cfg);
 }
 
 static struct xc5000_config xc5000_cfg;
@@ -356,12 +380,13 @@ static void set_type(struct i2c_client *c, unsigned int type,
        }
 
        /* discard private data, in case set_type() was previously called */
-       if (analog_ops->release)
-               analog_ops->release(&t->fe);
+       tuner_detach(&t->fe);
+       t->fe.analog_demod_priv = NULL;
 
        switch (t->type) {
        case TUNER_MT2032:
-               microtune_attach(&t->fe, t->i2c->adapter, t->i2c->addr);
+               dvb_attach(microtune_attach,
+                          &t->fe, t->i2c->adapter, t->i2c->addr);
                break;
        case TUNER_PHILIPS_TDA8290:
        {
@@ -369,12 +394,14 @@ static void set_type(struct i2c_client *c, unsigned int type,
                break;
        }
        case TUNER_TEA5767:
-               if (!tea5767_attach(&t->fe, t->i2c->adapter, t->i2c->addr))
+               if (!dvb_attach(tea5767_attach, &t->fe,
+                               t->i2c->adapter, t->i2c->addr))
                        goto attach_failed;
                t->mode_mask = T_RADIO;
                break;
        case TUNER_TEA5761:
-               if (!tea5761_attach(&t->fe, t->i2c->adapter, t->i2c->addr))
+               if (!dvb_attach(tea5761_attach, &t->fe,
+                               t->i2c->adapter, t->i2c->addr))
                        goto attach_failed;
                t->mode_mask = T_RADIO;
                break;
@@ -388,8 +415,8 @@ static void set_type(struct i2c_client *c, unsigned int type,
                buffer[2] = 0x86;
                buffer[3] = 0x54;
                i2c_master_send(c, buffer, 4);
-               if (!simple_tuner_attach(&t->fe, t->i2c->adapter, t->i2c->addr,
-                                       t->type))
+               if (!dvb_attach(simple_tuner_attach, &t->fe,
+                               t->i2c->adapter, t->i2c->addr, t->type))
                        goto attach_failed;
                break;
        case TUNER_PHILIPS_TD1316:
@@ -397,9 +424,9 @@ static void set_type(struct i2c_client *c, unsigned int type,
                buffer[1] = 0xdc;
                buffer[2] = 0x86;
                buffer[3] = 0xa4;
-               i2c_master_send(c,buffer,4);
-               if (!simple_tuner_attach(&t->fe, t->i2c->adapter,
-                                       t->i2c->addr, t->type))
+               i2c_master_send(c, buffer, 4);
+               if (!dvb_attach(simple_tuner_attach, &t->fe,
+                               t->i2c->adapter, t->i2c->addr, t->type))
                        goto attach_failed;
                break;
        case TUNER_XC2028:
@@ -409,12 +436,13 @@ static void set_type(struct i2c_client *c, unsigned int type,
                        .i2c_addr  = t->i2c->addr,
                        .callback  = t->tuner_callback,
                };
-               if (!xc2028_attach(&t->fe, &cfg))
+               if (!dvb_attach(xc2028_attach, &t->fe, &cfg))
                        goto attach_failed;
                break;
        }
        case TUNER_TDA9887:
-               tda9887_attach(&t->fe, t->i2c->adapter, t->i2c->addr);
+               dvb_attach(tda9887_attach,
+                          &t->fe, t->i2c->adapter, t->i2c->addr);
                break;
        case TUNER_XC5000:
        {
@@ -424,7 +452,8 @@ static void set_type(struct i2c_client *c, unsigned int type,
                xc5000_cfg.if_khz         = 5380;
                xc5000_cfg.priv           = c->adapter->algo_data;
                xc5000_cfg.tuner_callback = t->tuner_callback;
-               if (!xc5000_attach(&t->fe, t->i2c->adapter, &xc5000_cfg))
+               if (!dvb_attach(xc5000_attach,
+                               &t->fe, t->i2c->adapter, &xc5000_cfg))
                        goto attach_failed;
 
                xc_tuner_ops = &t->fe.ops.tuner_ops;
@@ -433,8 +462,8 @@ static void set_type(struct i2c_client *c, unsigned int type,
                break;
        }
        default:
-               if (!simple_tuner_attach(&t->fe, t->i2c->adapter,
-                                       t->i2c->addr, t->type))
+               if (!dvb_attach(simple_tuner_attach, &t->fe,
+                               t->i2c->adapter, t->i2c->addr, t->type))
                        goto attach_failed;
 
                break;
@@ -442,12 +471,14 @@ static void set_type(struct i2c_client *c, unsigned int type,
 
        if ((NULL == analog_ops->set_params) &&
            (fe_tuner_ops->set_analog_params)) {
+
                strlcpy(t->i2c->name, fe_tuner_ops->info.name,
                        sizeof(t->i2c->name));
 
                t->fe.analog_demod_priv = t;
                memcpy(analog_ops, &tuner_core_ops,
                       sizeof(struct analog_demod_ops));
+
        } else {
                strlcpy(t->i2c->name, analog_ops->info.name,
                        sizeof(t->i2c->name));
@@ -645,8 +676,8 @@ static void tuner_status(struct dvb_frontend *fe)
 {
        struct tuner *t = fe->analog_demod_priv;
        unsigned long freq, freq_fraction;
-       struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
-       struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
+       struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
+       struct analog_demod_ops *analog_ops = &fe->ops.analog_ops;
        const char *p;
 
        switch (t->mode) {
@@ -730,8 +761,10 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
        struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
        struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
 
-       if (tuner_debug>1)
+       if (tuner_debug > 1) {
                v4l_i2c_print_ioctl(client,cmd);
+               printk("\n");
+       }
 
        switch (cmd) {
        /* --- configuration --- */
@@ -1073,7 +1106,8 @@ static void tuner_lookup(struct i2c_adapter *adap,
 /* During client attach, set_type is called by adapter's attach_inform callback.
    set_type must then be completed by tuner_probe.
  */
-static int tuner_probe(struct i2c_client *client)
+static int tuner_probe(struct i2c_client *client,
+                      const struct i2c_device_id *id)
 {
        struct tuner *t;
        struct tuner *radio;
@@ -1111,8 +1145,9 @@ static int tuner_probe(struct i2c_client *client)
        if (!no_autodetect) {
                switch (client->addr) {
                case 0x10:
-                       if (tea5761_autodetection(t->i2c->adapter,
-                                                 t->i2c->addr) >= 0) {
+                       if (tuner_symbol_probe(tea5761_autodetection,
+                                              t->i2c->adapter,
+                                              t->i2c->addr) >= 0) {
                                t->type = TUNER_TEA5761;
                                t->mode_mask = T_RADIO;
                                t->mode = T_STANDBY;
@@ -1131,8 +1166,8 @@ static int tuner_probe(struct i2c_client *client)
                case 0x4b:
                        /* If chip is not tda8290, don't register.
                           since it can be tda9887*/
-                       if (tda829x_probe(t->i2c->adapter,
-                                         t->i2c->addr) == 0) {
+                       if (tuner_symbol_probe(tda829x_probe, t->i2c->adapter,
+                                              t->i2c->addr) == 0) {
                                tuner_dbg("tda829x detected\n");
                        } else {
                                /* Default is being tda9887 */
@@ -1144,7 +1179,8 @@ static int tuner_probe(struct i2c_client *client)
                        }
                        break;
                case 0x60:
-                       if (tea5767_autodetection(t->i2c->adapter, t->i2c->addr)
+                       if (tuner_symbol_probe(tea5767_autodetection,
+                                              t->i2c->adapter, t->i2c->addr)
                                        != EINVAL) {
                                t->type = TUNER_TEA5767;
                                t->mode_mask = T_RADIO;
@@ -1233,10 +1269,9 @@ static int tuner_legacy_probe(struct i2c_adapter *adap)
 static int tuner_remove(struct i2c_client *client)
 {
        struct tuner *t = i2c_get_clientdata(client);
-       struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
 
-       if (analog_ops->release)
-               analog_ops->release(&t->fe);
+       tuner_detach(&t->fe);
+       t->fe.analog_demod_priv = NULL;
 
        list_del(&t->list);
        kfree(t);
index f29a2cd0f2f27c3db0afead3d5a7f65ba7f8fd56..6f9945b04e1f2bcd676f0ed8dc910994b29ed300 100644 (file)
@@ -1461,7 +1461,7 @@ static struct CHIPDESC chiplist[] = {
 /* ---------------------------------------------------------------------- */
 /* i2c registration                                                       */
 
-static int chip_probe(struct i2c_client *client)
+static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
        struct CHIPSTATE *chip;
        struct CHIPDESC  *desc;
index bd201397a2acdb350824f7062119dfb93e5ee1b7..93bfd19dec7d6fdad7da5d4d6cf111e82327248e 100644 (file)
@@ -195,7 +195,8 @@ static int upd64031a_command(struct i2c_client *client, unsigned cmd, void *arg)
 
 /* i2c implementation */
 
-static int upd64031a_probe(struct i2c_client *client)
+static int upd64031a_probe(struct i2c_client *client,
+                          const struct i2c_device_id *id)
 {
        struct upd64031a_state *state;
        int i;
index 2d9a88f70c85ba2ac2efdebb9ac02d895ddea50c..9ab712a56ce0a9e1e4b11940a6770c3672c7b1a6 100644 (file)
@@ -172,7 +172,8 @@ static int upd64083_command(struct i2c_client *client, unsigned cmd, void *arg)
 
 /* i2c implementation */
 
-static int upd64083_probe(struct i2c_client *client)
+static int upd64083_probe(struct i2c_client *client,
+                         const struct i2c_device_id *id)
 {
        struct upd64083_state *state;
        int i;
index 64819353276a6a2f2540175625ab0bf42e4fac23..17f542dfb366c6588aeba260f4ce3b599405d6d9 100644 (file)
 
 #define VICAM_HEADER_SIZE       64
 
-#define clamp( x, l, h )        max_t( __typeof__( x ),         \
-                                      ( l ),                   \
-                                      min_t( __typeof__( x ),  \
-                                             ( h ),            \
-                                             ( x ) ) )
-
 /* Not sure what all the bytes in these char
  * arrays do, but they're necessary to make
  * the camera work.
index fc24ef05b3f31cf527b6fc850423cae317ad224b..74e1d3075a20c28d34f27f171bd09019e230373c 100644 (file)
@@ -1,7 +1,7 @@
 config VIDEO_USBVISION
        tristate "USB video devices based on Nogatech NT1003/1004/1005"
        depends on I2C && VIDEO_V4L2
-       select VIDEO_TUNER
+       select MEDIA_TUNER
        select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
        ---help---
          There are more than 50 different USB video devices based on
index 9ac92a80c645442ecba5d038e75b9479bebb05d6..338718750945bf8feb63e3d00a8e254b6781a3cc 100644 (file)
@@ -3,3 +3,4 @@ usbvision-objs  := usbvision-core.o usbvision-video.o usbvision-i2c.o usbvision-
 obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o
 
 EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
index 7cc42c1da457174eb862e671c16b692df1814444..e9dd996fd5df1f6084930345b076e95a12d16941 100644 (file)
@@ -710,7 +710,8 @@ EXPORT_SYMBOL(v4l2_chip_ident_i2c_client);
 /* Helper function for I2C legacy drivers */
 
 int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver *driver,
-               const char *name, int (*probe)(struct i2c_client *))
+               const char *name,
+               int (*probe)(struct i2c_client *, const struct i2c_device_id *))
 {
        struct i2c_client *client;
        int err;
@@ -724,7 +725,7 @@ int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver
        client->driver = driver;
        strlcpy(client->name, name, sizeof(client->name));
 
-       err = probe(client);
+       err = probe(client, NULL);
        if (err == 0) {
                i2c_attach_client(client);
        } else {
index 282c81403c976a2c1ecfefc693e9019aa24613b0..fac0deba24afc69b67d07963c557ecc748e24c84 100644 (file)
@@ -121,7 +121,8 @@ static int vp27smpx_command(struct i2c_client *client, unsigned cmd, void *arg)
  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  */
 
-static int vp27smpx_probe(struct i2c_client *client)
+static int vp27smpx_probe(struct i2c_client *client,
+                         const struct i2c_device_id *id)
 {
        struct vp27smpx_state *state;
 
index 31795b4f8b6316e2e480ac838a53d52840660de4..0f8ed8461fba25f7c70f0a3bd9573f4698569a03 100644 (file)
@@ -261,7 +261,8 @@ static int wm8739_command(struct i2c_client *client, unsigned cmd, void *arg)
 
 /* i2c implementation */
 
-static int wm8739_probe(struct i2c_client *client)
+static int wm8739_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
 {
        struct wm8739_state *state;
 
index 869f9e7946b6082bb9df221ccc056d13e808e0d9..67a409e60c46559b4aa76fe820ac60b2a88e07b5 100644 (file)
@@ -159,7 +159,8 @@ static int wm8775_command(struct i2c_client *client, unsigned cmd, void *arg)
  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  */
 
-static int wm8775_probe(struct i2c_client *client)
+static int wm8775_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
 {
        struct wm8775_state *state;
 
index 328ed6e7ac6abe5388a30a90b3b9752e01c9c842..870bc5a70e3fdf7fb41f12b5142bba4c050722c4 100644 (file)
@@ -180,6 +180,7 @@ static ssize_t zoran_write(struct file *file, const char __user *buffer,
 }
 
 static const struct file_operations zoran_operations = {
+       .owner          = THIS_MODULE,
        .open           = zoran_open,
        .read           = seq_read,
        .write          = zoran_write,
@@ -195,10 +196,8 @@ zoran_proc_init (struct zoran *zr)
        char name[8];
 
        snprintf(name, 7, "zoran%d", zr->id);
-       if ((zr->zoran_proc = create_proc_entry(name, 0, NULL))) {
-               zr->zoran_proc->data = zr;
-               zr->zoran_proc->owner = THIS_MODULE;
-               zr->zoran_proc->proc_fops = &zoran_operations;
+       zr->zoran_proc = proc_create_data(name, 0, NULL, &zoran_operations, zr);
+       if (zr->zoran_proc != NULL) {
                dprintk(2,
                        KERN_INFO
                        "%s: procfs entry /proc/%s allocated. data=%p\n",
index a95314897402b53cd7d677e0eff4c8a27966668e..81483de8c0fdfeae0262dc745a1147ca5c28f966 100644 (file)
@@ -371,7 +371,7 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req)
        /* connect the i2o_block_request to the request */
        if (!req->special) {
                ireq = i2o_block_request_alloc();
-               if (unlikely(IS_ERR(ireq))) {
+               if (IS_ERR(ireq)) {
                        osm_debug("unable to allocate i2o_block_request!\n");
                        return BLKPREP_DEFER;
                }
index 6fdd072201f990e4b975724bef3668b08f44dfac..54a3016ff45de24afd2430ff538c6d3bb9bf6484 100644 (file)
@@ -1893,13 +1893,11 @@ static int i2o_proc_create_entries(struct proc_dir_entry *dir,
        struct proc_dir_entry *tmp;
 
        while (i2o_pe->name) {
-               tmp = create_proc_entry(i2o_pe->name, i2o_pe->mode, dir);
+               tmp = proc_create_data(i2o_pe->name, i2o_pe->mode, dir,
+                                      i2o_pe->fops, data);
                if (!tmp)
                        return -1;
 
-               tmp->data = data;
-               tmp->proc_fops = i2o_pe->fops;
-
                i2o_pe++;
        }
 
index f6f2d960cadbef6e883842b4b43b09a85947f4ea..ef8a492766a72b5d13076bd8f8d7ab9cf4a0e6f5 100644 (file)
@@ -132,7 +132,7 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc)
 
        if (iter >= MAX_ASIC_ISR_LOOPS)
                printk(KERN_ERR "%s: interrupt processing overrun\n",
-                      __FUNCTION__);
+                      __func__);
 }
 
 static inline int asic3_irq_to_bank(struct asic3 *asic, int irq)
@@ -409,7 +409,7 @@ int asic3_gpio_get_value(struct asic3 *asic, unsigned gpio)
                return asic3_get_gpio_d(asic, Status) & mask;
        default:
                printk(KERN_ERR "%s: invalid GPIO value 0x%x",
-                      __FUNCTION__, gpio);
+                      __func__, gpio);
                return -EINVAL;
        }
 }
@@ -437,7 +437,7 @@ void asic3_gpio_set_value(struct asic3 *asic, unsigned gpio, int val)
                return;
        default:
                printk(KERN_ERR "%s: invalid GPIO value 0x%x",
-                      __FUNCTION__, gpio);
+                      __func__, gpio);
                return;
        }
 }
index 4edc120a6359490a816eca96f30dbbc3a5eda624..633cbba072f024f013a17f42cc8b3181c63ef8a4 100644 (file)
@@ -132,8 +132,9 @@ static struct ds1wm_platform_data ds1wm_pdata = {
        .disable   = ds1wm_disable,
 };
 
-static int ds1wm_device_add(struct device *pasic3_dev, int bus_shift)
+static int ds1wm_device_add(struct platform_device *pasic3_pdev, int bus_shift)
 {
+       struct device *pasic3_dev = &pasic3_pdev->dev;
        struct pasic3_data *asic = pasic3_dev->driver_data;
        struct platform_device *pdev;
        int ret;
@@ -144,8 +145,8 @@ static int ds1wm_device_add(struct device *pasic3_dev, int bus_shift)
                return -ENOMEM;
        }
 
-       ret = platform_device_add_resources(pdev, pdev->resource,
-                                               pdev->num_resources);
+       ret = platform_device_add_resources(pdev, pasic3_pdev->resource,
+                                               pasic3_pdev->num_resources);
        if (ret < 0) {
                dev_dbg(pasic3_dev, "failed to add DS1WM resources\n");
                goto exit_pdev_put;
@@ -207,7 +208,7 @@ static int __init pasic3_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
-       ret = ds1wm_device_add(dev, asic->bus_shift);
+       ret = ds1wm_device_add(pdev, asic->bus_shift);
        if (ret < 0)
                dev_warn(dev, "failed to register DS1WM\n");
 
index 6e655b4c6682eac2e830f78e9db5eaf262f916cd..2fe64734d8afd2d6e893e40224ee56ff6b935706 100644 (file)
@@ -349,11 +349,11 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
        mode &= 3;              /* get current power mode */
 
        if (unit >= ARRAY_SIZE(sm->unit_power)) {
-               dev_err(dev, "%s: bad unit %d\n", __FUNCTION__, unit);
+               dev_err(dev, "%s: bad unit %d\n", __func__, unit);
                goto already;
        }
 
-       dev_dbg(sm->dev, "%s: unit %d, cur %d, to %d\n", __FUNCTION__, unit,
+       dev_dbg(sm->dev, "%s: unit %d, cur %d, to %d\n", __func__, unit,
                sm->unit_power[unit], to);
 
        if (to == 0 && sm->unit_power[unit] == 0) {
index 302e92418bbef2464e0e3f8fdf85edbb47729a20..ff51ab67231c95a9605496ced2ab104cd9ed5105 100644 (file)
@@ -210,13 +210,10 @@ static int hdpu_cpustate_probe(struct platform_device *pdev)
                return ret;
        }
 
-       proc_de = create_proc_entry("sky_cpustate", 0666, &proc_root);
+       proc_de = proc_create("sky_cpustate", 0666, NULL, &proc_cpustate);
        if (!proc_de) {
                printk(KERN_WARNING "sky_cpustate: "
                       "Unable to create proc entry\n");
-       } else {
-               proc_de->proc_fops = &proc_cpustate;
-               proc_de->owner = THIS_MODULE;
        }
 
        printk(KERN_INFO "Sky CPU State Driver v" SKY_CPUSTATE_VERSION "\n");
index 2fa36f7a6eb388ec02db087560ec3dca4c8b2d1d..08e26beefe64182f78f509343bcdbc5156d81aca 100644 (file)
@@ -102,22 +102,17 @@ static int hdpu_nexus_probe(struct platform_device *pdev)
                printk(KERN_ERR "sky_nexus: Could not map slot id\n");
        }
 
-       hdpu_slot_id = create_proc_entry("sky_slot_id", 0666, &proc_root);
+       hdpu_slot_id = proc_create("sky_slot_id", 0666, NULL, &proc_slot_id);
        if (!hdpu_slot_id) {
                printk(KERN_WARNING "sky_nexus: "
                       "Unable to create proc dir entry: sky_slot_id\n");
-       } else {
-               hdpu_slot_id->proc_fops = &proc_slot_id;
-               hdpu_slot_id->owner = THIS_MODULE;
        }
 
-       hdpu_chassis_id = create_proc_entry("sky_chassis_id", 0666, &proc_root);
-       if (!hdpu_chassis_id) {
+       hdpu_chassis_id = proc_create("sky_chassis_id", 0666, NULL,
+                                     &proc_chassis_id);
+       if (!hdpu_chassis_id)
                printk(KERN_WARNING "sky_nexus: "
                       "Unable to create proc dir entry: sky_chassis_id\n");
-       } else {
-               hdpu_chassis_id->proc_fops = &proc_chassis_id;
-               hdpu_chassis_id->owner = THIS_MODULE;
        }
 
        return 0;
@@ -128,8 +123,8 @@ static int hdpu_nexus_remove(struct platform_device *pdev)
        slot_id = -1;
        chassis_id = -1;
 
-       remove_proc_entry("sky_slot_id", &proc_root);
-       remove_proc_entry("sky_chassis_id", &proc_root);
+       remove_proc_entry("sky_slot_id", NULL);
+       remove_proc_entry("sky_chassis_id", NULL);
 
        hdpu_slot_id = 0;
        hdpu_chassis_id = 0;
index 1a0e7978226a6b593e048e31ef00e4e40dd13d41..276d3fb68094a53d6815979688b89cd412e8b489 100644 (file)
@@ -96,7 +96,7 @@ static inline void do_exec_command(struct service_processor *sp)
 {
        char tsbuf[32];
 
-       dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
+       dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));
 
        if (ibmasm_send_i2o_message(sp)) {
                sp->current_command->status = IBMASM_CMD_FAILED;
@@ -119,7 +119,7 @@ void ibmasm_exec_command(struct service_processor *sp, struct command *cmd)
        unsigned long flags;
        char tsbuf[32];
 
-       dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
+       dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));
 
        spin_lock_irqsave(&sp->lock, flags);
 
@@ -139,7 +139,7 @@ static void exec_next_command(struct service_processor *sp)
        unsigned long flags;
        char tsbuf[32];
 
-       dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
+       dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));
 
        spin_lock_irqsave(&sp->lock, flags);
        sp->current_command = dequeue_command(sp);
index 3036e785b3e4c8e6ab8c4cfb1a9b1e29e89caf39..1bc4306572a477aa6d440187c5bb7db4a23e7a26 100644 (file)
@@ -75,9 +75,9 @@ void ibmasm_heartbeat_exit(struct service_processor *sp)
 {
        char tsbuf[32];
 
-       dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
+       dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));
        ibmasm_wait_for_response(sp->heartbeat, IBMASM_CMD_TIMEOUT_NORMAL);
-       dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
+       dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));
        suspend_heartbeats = 1;
        command_put(sp->heartbeat);
 }
@@ -88,7 +88,7 @@ void ibmasm_receive_heartbeat(struct service_processor *sp,  void *message, size
        struct dot_command_header *header = (struct dot_command_header *)cmd->buffer;
        char tsbuf[32];
 
-       dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
+       dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf));
        if (suspend_heartbeats)
                return;
 
index 0c0bb3093e07e7ab1afea5c37acfb38ac83394dc..80a1363524087a1e66e575058360d071bbca352f 100644 (file)
@@ -175,19 +175,17 @@ static int intel_menlow_memory_add(struct acpi_device *device)
                goto end;
        }
 
-       if (cdev) {
-               acpi_driver_data(device) = cdev;
-               result = sysfs_create_link(&device->dev.kobj,
-                                       &cdev->device.kobj, "thermal_cooling");
-               if (result)
-                       goto unregister;
-
-               result = sysfs_create_link(&cdev->device.kobj,
-                                       &device->dev.kobj, "device");
-               if (result) {
-                       sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
-                       goto unregister;
-               }
+       acpi_driver_data(device) = cdev;
+       result = sysfs_create_link(&device->dev.kobj,
+                               &cdev->device.kobj, "thermal_cooling");
+       if (result)
+               goto unregister;
+
+       result = sysfs_create_link(&cdev->device.kobj,
+                               &device->dev.kobj, "device");
+       if (result) {
+               sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
+               goto unregister;
        }
 
  end:
index 05172d2613d66d3f980c2b2c148bd40992c4e64d..6f76573e7c8a244bdac0be865a1a1df72bfee94c 100644 (file)
@@ -75,7 +75,7 @@ ioc4_register_submodule(struct ioc4_submodule *is)
                        printk(KERN_WARNING
                               "%s: IOC4 submodule %s probe failed "
                               "for pci_dev %s",
-                              __FUNCTION__, module_name(is->is_owner),
+                              __func__, module_name(is->is_owner),
                               pci_name(idd->idd_pdev));
                }
        }
@@ -102,7 +102,7 @@ ioc4_unregister_submodule(struct ioc4_submodule *is)
                        printk(KERN_WARNING
                               "%s: IOC4 submodule %s remove failed "
                               "for pci_dev %s.\n",
-                              __FUNCTION__, module_name(is->is_owner),
+                              __func__, module_name(is->is_owner),
                               pci_name(idd->idd_pdev));
                }
        }
@@ -282,7 +282,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
        if ((ret = pci_enable_device(pdev))) {
                printk(KERN_WARNING
                       "%s: Failed to enable IOC4 device for pci_dev %s.\n",
-                      __FUNCTION__, pci_name(pdev));
+                      __func__, pci_name(pdev));
                goto out;
        }
        pci_set_master(pdev);
@@ -292,7 +292,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
        if (!idd) {
                printk(KERN_WARNING
                       "%s: Failed to allocate IOC4 data for pci_dev %s.\n",
-                      __FUNCTION__, pci_name(pdev));
+                      __func__, pci_name(pdev));
                ret = -ENODEV;
                goto out_idd;
        }
@@ -307,7 +307,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
                printk(KERN_WARNING
                       "%s: Unable to find IOC4 misc resource "
                       "for pci_dev %s.\n",
-                      __FUNCTION__, pci_name(idd->idd_pdev));
+                      __func__, pci_name(idd->idd_pdev));
                ret = -ENODEV;
                goto out_pci;
        }
@@ -316,7 +316,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
                printk(KERN_WARNING
                       "%s: Unable to request IOC4 misc region "
                       "for pci_dev %s.\n",
-                      __FUNCTION__, pci_name(idd->idd_pdev));
+                      __func__, pci_name(idd->idd_pdev));
                ret = -ENODEV;
                goto out_pci;
        }
@@ -326,7 +326,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
                printk(KERN_WARNING
                       "%s: Unable to remap IOC4 misc region "
                       "for pci_dev %s.\n",
-                      __FUNCTION__, pci_name(idd->idd_pdev));
+                      __func__, pci_name(idd->idd_pdev));
                ret = -ENODEV;
                goto out_misc_region;
        }
@@ -372,7 +372,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
                        printk(KERN_WARNING
                               "%s: IOC4 submodule 0x%s probe failed "
                               "for pci_dev %s.\n",
-                              __FUNCTION__, module_name(is->is_owner),
+                              __func__, module_name(is->is_owner),
                               pci_name(idd->idd_pdev));
                }
        }
@@ -406,7 +406,7 @@ ioc4_remove(struct pci_dev *pdev)
                        printk(KERN_WARNING
                               "%s: IOC4 submodule 0x%s remove failed "
                               "for pci_dev %s.\n",
-                              __FUNCTION__, module_name(is->is_owner),
+                              __func__, module_name(is->is_owner),
                               pci_name(idd->idd_pdev));
                }
        }
@@ -418,7 +418,7 @@ ioc4_remove(struct pci_dev *pdev)
                printk(KERN_WARNING
                       "%s: Unable to get IOC4 misc mapping for pci_dev %s. "
                       "Device removal may be incomplete.\n",
-                      __FUNCTION__, pci_name(idd->idd_pdev));
+                      __func__, pci_name(idd->idd_pdev));
        }
        release_mem_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
 
index 7fa61e907e1c115b16f14936ffea65f865816f4e..71d1c84e2fa8e4ed918461a702d2e50e2d4b3ccd 100644 (file)
@@ -12,6 +12,7 @@
  *  or alternatively, you might use OpenHaptics provided by Sensable.
  */
 
+#include <linux/compat.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/device.h>
@@ -91,11 +92,8 @@ static long phantom_ioctl(struct file *file, unsigned int cmd,
        unsigned long flags;
        unsigned int i;
 
-       if (_IOC_TYPE(cmd) != PH_IOC_MAGIC ||
-                       _IOC_NR(cmd) > PH_IOC_MAXNR)
-               return -ENOTTY;
-
        switch (cmd) {
+       case PHN_SETREG:
        case PHN_SET_REG:
                if (copy_from_user(&r, argp, sizeof(r)))
                        return -EFAULT;
@@ -126,6 +124,7 @@ static long phantom_ioctl(struct file *file, unsigned int cmd,
                        phantom_status(dev, dev->status & ~PHB_RUNNING);
                spin_unlock_irqrestore(&dev->regs_lock, flags);
                break;
+       case PHN_SETREGS:
        case PHN_SET_REGS:
                if (copy_from_user(&rs, argp, sizeof(rs)))
                        return -EFAULT;
@@ -143,6 +142,7 @@ static long phantom_ioctl(struct file *file, unsigned int cmd,
                }
                spin_unlock_irqrestore(&dev->regs_lock, flags);
                break;
+       case PHN_GETREG:
        case PHN_GET_REG:
                if (copy_from_user(&r, argp, sizeof(r)))
                        return -EFAULT;
@@ -155,6 +155,7 @@ static long phantom_ioctl(struct file *file, unsigned int cmd,
                if (copy_to_user(argp, &r, sizeof(r)))
                        return -EFAULT;
                break;
+       case PHN_GETREGS:
        case PHN_GET_REGS: {
                u32 m;
 
@@ -168,6 +169,7 @@ static long phantom_ioctl(struct file *file, unsigned int cmd,
                for (i = 0; i < m; i++)
                        if (rs.mask & BIT(i))
                                rs.values[i] = ioread32(dev->iaddr + i);
+               atomic_set(&dev->counter, 0);
                spin_unlock_irqrestore(&dev->regs_lock, flags);
 
                if (copy_to_user(argp, &rs, sizeof(rs)))
@@ -191,6 +193,20 @@ static long phantom_ioctl(struct file *file, unsigned int cmd,
        return 0;
 }
 
+#ifdef CONFIG_COMPAT
+static long phantom_compat_ioctl(struct file *filp, unsigned int cmd,
+               unsigned long arg)
+{
+       if (_IOC_NR(cmd) <= 3 && _IOC_SIZE(cmd) == sizeof(compat_uptr_t)) {
+               cmd &= ~(_IOC_SIZEMASK << _IOC_SIZESHIFT);
+               cmd |= sizeof(void *) << _IOC_SIZESHIFT;
+       }
+       return phantom_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
+}
+#else
+#define phantom_compat_ioctl NULL
+#endif
+
 static int phantom_open(struct inode *inode, struct file *file)
 {
        struct phantom_device *dev = container_of(inode->i_cdev,
@@ -239,11 +255,12 @@ static unsigned int phantom_poll(struct file *file, poll_table *wait)
 
        pr_debug("phantom_poll: %d\n", atomic_read(&dev->counter));
        poll_wait(file, &dev->wait, wait);
-       if (atomic_read(&dev->counter)) {
+
+       if (!(dev->status & PHB_RUNNING))
+               mask = POLLERR;
+       else if (atomic_read(&dev->counter))
                mask = POLLIN | POLLRDNORM;
-               atomic_dec(&dev->counter);
-       } else if ((dev->status & PHB_RUNNING) == 0)
-               mask = POLLIN | POLLRDNORM | POLLERR;
+
        pr_debug("phantom_poll end: %x/%d\n", mask, atomic_read(&dev->counter));
 
        return mask;
@@ -253,6 +270,7 @@ static struct file_operations phantom_file_ops = {
        .open = phantom_open,
        .release = phantom_release,
        .unlocked_ioctl = phantom_ioctl,
+       .compat_ioctl = phantom_compat_ioctl,
        .poll = phantom_poll,
 };
 
index 27e200ec582692e42b5d9186a15b953a3a323bf5..acd3fd4285d7c954c824286a804c48c6a75d39ce 100644 (file)
@@ -211,7 +211,7 @@ xpc_rsvd_page_init(void)
         */
        amos_page = xpc_vars->amos_page;
        if (amos_page == NULL) {
-               amos_page = (AMO_t *)TO_AMO(uncached_alloc_page(0));
+               amos_page = (AMO_t *)TO_AMO(uncached_alloc_page(0, 1));
                if (amos_page == NULL) {
                        dev_err(xpc_part, "can't allocate page of AMOs\n");
                        return NULL;
@@ -230,7 +230,7 @@ xpc_rsvd_page_init(void)
                                dev_err(xpc_part, "can't change memory "
                                        "protections\n");
                                uncached_free_page(__IA64_UNCACHED_OFFSET |
-                                                  TO_PHYS((u64)amos_page));
+                                                  TO_PHYS((u64)amos_page), 1);
                                return NULL;
                        }
                }
index 02ff3d19b1ccaf40981c861e9977c43eea634f3f..00e48e2a9c11229da5576897d566fead0ac2a8f4 100644 (file)
@@ -961,7 +961,7 @@ static int sony_nc_resume(struct acpi_device *device)
                ret = acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset,
                                       item->value, NULL);
                if (ret < 0) {
-                       printk("%s: %d\n", __FUNCTION__, ret);
+                       printk("%s: %d\n", __func__, ret);
                        break;
                }
        }
@@ -1453,7 +1453,7 @@ static struct sonypi_eventtypes type4_events[] = {
                udelay(1);                                              \
        if (!n)                                                         \
                dprintk("command failed at %s : %s (line %d)\n",        \
-                               __FILE__, __FUNCTION__, __LINE__);      \
+                               __FILE__, __func__, __LINE__);  \
 }
 
 static u8 sony_pic_call1(u8 dev)
index 365024b83d3da9df9b6e4f7a9d4cf6d216ba523d..35508584ac2ae55ffae78479877fe67b32a3a7d2 100644 (file)
@@ -340,7 +340,7 @@ checkstatus:
 
        /* SPI R3, R4, or R7 == R1 + 4 bytes */
        case MMC_RSP_SPI_R3:
-               cmd->resp[1] = be32_to_cpu(get_unaligned((u32 *)cp));
+               cmd->resp[1] = get_unaligned_be32(cp);
                break;
 
        /* SPI R1 == just one status byte */
index 95244a7e73531ad0fdf2d451d907edabcfbf5a4c..626ac083f4e09c294c4d465dd3c85e886082867d 100644 (file)
@@ -213,9 +213,10 @@ static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int rema
        void __iomem *base = host->base;
        char *ptr = buffer;
        u32 status;
+       int host_remain = host->size;
 
        do {
-               int count = host->size - (readl(base + MMCIFIFOCNT) << 2);
+               int count = host_remain - (readl(base + MMCIFIFOCNT) << 2);
 
                if (count > remain)
                        count = remain;
@@ -227,6 +228,7 @@ static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int rema
 
                ptr += count;
                remain -= count;
+               host_remain -= count;
 
                if (remain == 0)
                        break;
index ba6bd03a015ff6afad60ae65d8c614b35a6671d4..a637910b02dd74766f4c79ebed4385dea8fb18f4 100644 (file)
@@ -693,11 +693,15 @@ static int __init am79c961_probe(struct platform_device *pdev)
         * done by the ether bootp loader.
         */
        dev->base_addr = res->start;
-       dev->irq = platform_get_irq(pdev, 0);
+       ret = platform_get_irq(pdev, 0);
 
-       ret = -ENODEV;
-       if (dev->irq < 0)
+       if (ret < 0) {
+               ret = -ENODEV;
                goto nodev;
+       }
+       dev->irq = ret;
+
+       ret = -ENODEV;
        if (!request_region(dev->base_addr, 0x18, dev->name))
                goto nodev;
 
index 6e91b4b7aabb3402629571288f43754a3b67f104..6425603bc37976bebbec44283b37f4d377325c65 100644 (file)
@@ -3282,17 +3282,14 @@ static int bond_create_proc_entry(struct bonding *bond)
        struct net_device *bond_dev = bond->dev;
 
        if (bond_proc_dir) {
-               bond->proc_entry = create_proc_entry(bond_dev->name,
-                                                    S_IRUGO,
-                                                    bond_proc_dir);
+               bond->proc_entry = proc_create_data(bond_dev->name,
+                                                   S_IRUGO, bond_proc_dir,
+                                                   &bond_info_fops, bond);
                if (bond->proc_entry == NULL) {
                        printk(KERN_WARNING DRV_NAME
                               ": Warning: Cannot create /proc/net/%s/%s\n",
                               DRV_NAME, bond_dev->name);
                } else {
-                       bond->proc_entry->data = bond;
-                       bond->proc_entry->proc_fops = &bond_info_fops;
-                       bond->proc_entry->owner = THIS_MODULE;
                        memcpy(bond->proc_file_name, bond_dev->name, IFNAMSIZ);
                }
        }
index 229303ff6a39016c0fd3823d7e5212ecc77fcaff..a0177fc55e28a9b241dbfdbd39fa5df1f24c268e 100644 (file)
@@ -38,7 +38,7 @@
 #define DRV_VERSION "1.0-ko"
 
 /* Firmware version */
-#define FW_VERSION_MAJOR 5
+#define FW_VERSION_MAJOR 6
 #define FW_VERSION_MINOR 0
 #define FW_VERSION_MICRO 0
 #endif                         /* __CHELSIO_VERSION_H */
index 2d139ec7977768e78112dd52513dcae57d5b5698..f3cba5e24ec511a7a08ea6c0659155850a165b00 100644 (file)
@@ -1802,7 +1802,7 @@ static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
         * it is protected by the before last buffer's el bit being set */
        if (rx->prev->skb) {
                struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data;
-               put_unaligned(cpu_to_le32(rx->dma_addr), &prev_rfd->link);
+               put_unaligned_le32(rx->dma_addr, &prev_rfd->link);
        }
 
        return 0;
index b53f6b6491b3f049bc69562dfbadf0536d47e409..e5c2380f50ca0ef8c45d371a4eb69c69f671dbe4 100644 (file)
@@ -1508,7 +1508,7 @@ static int hamachi_rx(struct net_device *dev)
                                            hmp->rx_buf_sz,
                                            PCI_DMA_FROMDEVICE);
                buf_addr = (u8 *) hmp->rx_skbuff[entry]->data;
-               frame_status = le32_to_cpu(get_unaligned((__le32*)&(buf_addr[data_size - 12])));
+               frame_status = get_unaligned_le32(&(buf_addr[data_size - 12]));
                if (hamachi_debug > 4)
                        printk(KERN_DEBUG "  hamachi_rx() status was %8.8x.\n",
                                frame_status);
index 1da55dd2a5a0a07b4e05340a050e618bbf805166..9d5721287d6f50d7030499e4470b41a36f4cb6b5 100644 (file)
@@ -148,13 +148,13 @@ static void sp_xmit_on_air(unsigned long channel)
 
        if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistence)) {
                sp->led_state = 0x70;
-               sp->tty->driver->write(sp->tty, &sp->led_state, 1);
+               sp->tty->ops->write(sp->tty, &sp->led_state, 1);
                sp->tx_enable = 1;
-               actual = sp->tty->driver->write(sp->tty, sp->xbuff, sp->status2);
+               actual = sp->tty->ops->write(sp->tty, sp->xbuff, sp->status2);
                sp->xleft -= actual;
                sp->xhead += actual;
                sp->led_state = 0x60;
-               sp->tty->driver->write(sp->tty, &sp->led_state, 1);
+               sp->tty->ops->write(sp->tty, &sp->led_state, 1);
                sp->status2 = 0;
        } else
                mod_timer(&sp->tx_t, jiffies + ((when + 1) * HZ) / 100);
@@ -220,13 +220,13 @@ static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
         */
        if (sp->duplex == 1) {
                sp->led_state = 0x70;
-               sp->tty->driver->write(sp->tty, &sp->led_state, 1);
+               sp->tty->ops->write(sp->tty, &sp->led_state, 1);
                sp->tx_enable = 1;
-               actual = sp->tty->driver->write(sp->tty, sp->xbuff, count);
+               actual = sp->tty->ops->write(sp->tty, sp->xbuff, count);
                sp->xleft = count - actual;
                sp->xhead = sp->xbuff + actual;
                sp->led_state = 0x60;
-               sp->tty->driver->write(sp->tty, &sp->led_state, 1);
+               sp->tty->ops->write(sp->tty, &sp->led_state, 1);
        } else {
                sp->xleft = count;
                sp->xhead = sp->xbuff;
@@ -444,7 +444,7 @@ static void sixpack_write_wakeup(struct tty_struct *tty)
        }
 
        if (sp->tx_enable) {
-               actual = tty->driver->write(tty, sp->xhead, sp->xleft);
+               actual = tty->ops->write(tty, sp->xhead, sp->xleft);
                sp->xleft -= actual;
                sp->xhead += actual;
        }
@@ -491,9 +491,7 @@ static void sixpack_receive_buf(struct tty_struct *tty,
        sixpack_decode(sp, buf, count1);
 
        sp_put(sp);
-       if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
-           && tty->driver->unthrottle)
-               tty->driver->unthrottle(tty);
+       tty_unthrottle(tty);
 }
 
 /*
@@ -554,8 +552,8 @@ static void resync_tnc(unsigned long channel)
        /* resync the TNC */
 
        sp->led_state = 0x60;
-       sp->tty->driver->write(sp->tty, &sp->led_state, 1);
-       sp->tty->driver->write(sp->tty, &resync_cmd, 1);
+       sp->tty->ops->write(sp->tty, &sp->led_state, 1);
+       sp->tty->ops->write(sp->tty, &resync_cmd, 1);
 
 
        /* Start resync timer again -- the TNC might be still absent */
@@ -573,7 +571,7 @@ static inline int tnc_init(struct sixpack *sp)
 
        tnc_set_sync_state(sp, TNC_UNSYNC_STARTUP);
 
-       sp->tty->driver->write(sp->tty, &inbyte, 1);
+       sp->tty->ops->write(sp->tty, &inbyte, 1);
 
        del_timer(&sp->resync_t);
        sp->resync_t.data = (unsigned long) sp;
@@ -601,6 +599,8 @@ static int sixpack_open(struct tty_struct *tty)
 
        if (!capable(CAP_NET_ADMIN))
                return -EPERM;
+       if (tty->ops->write == NULL)
+               return -EOPNOTSUPP;
 
        dev = alloc_netdev(sizeof(struct sixpack), "sp%d", sp_setup);
        if (!dev) {
@@ -914,9 +914,9 @@ static void decode_prio_command(struct sixpack *sp, unsigned char cmd)
        } else { /* output watchdog char if idle */
                if ((sp->status2 != 0) && (sp->duplex == 1)) {
                        sp->led_state = 0x70;
-                       sp->tty->driver->write(sp->tty, &sp->led_state, 1);
+                       sp->tty->ops->write(sp->tty, &sp->led_state, 1);
                        sp->tx_enable = 1;
-                       actual = sp->tty->driver->write(sp->tty, sp->xbuff, sp->status2);
+                       actual = sp->tty->ops->write(sp->tty, sp->xbuff, sp->status2);
                        sp->xleft -= actual;
                        sp->xhead += actual;
                        sp->led_state = 0x60;
@@ -926,7 +926,7 @@ static void decode_prio_command(struct sixpack *sp, unsigned char cmd)
        }
 
        /* needed to trigger the TNC watchdog */
-       sp->tty->driver->write(sp->tty, &sp->led_state, 1);
+       sp->tty->ops->write(sp->tty, &sp->led_state, 1);
 
         /* if the state byte has been received, the TNC is present,
            so the resync timer can be reset. */
@@ -956,12 +956,12 @@ static void decode_std_command(struct sixpack *sp, unsigned char cmd)
                        if ((sp->status & SIXP_RX_DCD_MASK) ==
                                SIXP_RX_DCD_MASK) {
                                sp->led_state = 0x68;
-                               sp->tty->driver->write(sp->tty, &sp->led_state, 1);
+                               sp->tty->ops->write(sp->tty, &sp->led_state, 1);
                        }
                } else {
                        sp->led_state = 0x60;
                        /* fill trailing bytes with zeroes */
-                       sp->tty->driver->write(sp->tty, &sp->led_state, 1);
+                       sp->tty->ops->write(sp->tty, &sp->led_state, 1);
                        rest = sp->rx_count;
                        if (rest != 0)
                                 for (i = rest; i <= 3; i++)
index 30c9b3b0d1319fe0c18b4906594748ee3ddaa6e0..65166035aca0c81b5bea15d608bb88cf945ef24c 100644 (file)
@@ -516,7 +516,7 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len)
        spin_unlock_bh(&ax->buflock);
 
        set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags);
-       actual = ax->tty->driver->write(ax->tty, ax->xbuff, count);
+       actual = ax->tty->ops->write(ax->tty, ax->xbuff, count);
        ax->stats.tx_packets++;
        ax->stats.tx_bytes += actual;
 
@@ -546,7 +546,7 @@ static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
                }
 
                printk(KERN_ERR "mkiss: %s: transmit timed out, %s?\n", dev->name,
-                      (ax->tty->driver->chars_in_buffer(ax->tty) || ax->xleft) ?
+                      (ax->tty->ops->chars_in_buffer(ax->tty) || ax->xleft) ?
                       "bad line quality" : "driver error");
 
                ax->xleft = 0;
@@ -736,6 +736,8 @@ static int mkiss_open(struct tty_struct *tty)
 
        if (!capable(CAP_NET_ADMIN))
                return -EPERM;
+       if (tty->ops->write == NULL)
+               return -EOPNOTSUPP;
 
        dev = alloc_netdev(sizeof(struct mkiss), "ax%d", ax_setup);
        if (!dev) {
@@ -754,8 +756,7 @@ static int mkiss_open(struct tty_struct *tty)
        tty->disc_data = ax;
        tty->receive_room = 65535;
 
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       tty_driver_flush_buffer(tty);
 
        /* Restore default settings */
        dev->type = ARPHRD_AX25;
@@ -935,9 +936,7 @@ static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp,
        }
 
        mkiss_put(ax);
-       if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
-           && tty->driver->unthrottle)
-               tty->driver->unthrottle(tty);
+       tty_unthrottle(tty);
 }
 
 /*
@@ -962,7 +961,7 @@ static void mkiss_write_wakeup(struct tty_struct *tty)
                goto out;
        }
 
-       actual = tty->driver->write(tty, ax->xhead, ax->xleft);
+       actual = tty->ops->write(tty, ax->xhead, ax->xleft);
        ax->xleft -= actual;
        ax->xhead += actual;
 
index ce4fc2ec2fe4650af4fe4ee614ca9503e0060f86..00527805e4f170a8a1bdb6888aa2a30829210d6b 100644 (file)
@@ -1302,13 +1302,10 @@ static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter)
        if (ibmveth_proc_dir) {
                char u_addr[10];
                sprintf(u_addr, "%x", adapter->vdev->unit_address);
-               entry = create_proc_entry(u_addr, S_IFREG, ibmveth_proc_dir);
-               if (!entry) {
+               entry = proc_create_data(u_addr, S_IFREG, ibmveth_proc_dir,
+                                        &ibmveth_proc_fops, adapter);
+               if (!entry)
                        ibmveth_error_printk("Cannot create adapter proc entry");
-               } else {
-                       entry->data = (void *) adapter;
-                       entry->proc_fops = &ibmveth_proc_fops;
-               }
        }
        return;
 }
index fc753d7f674e41b0a231ac45663806c7b84ab06a..e6f40b7f9041d48e8c8b0d2020175dbff20e1331 100644 (file)
@@ -64,7 +64,7 @@ static int irtty_chars_in_buffer(struct sir_dev *dev)
        IRDA_ASSERT(priv != NULL, return -1;);
        IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
 
-       return priv->tty->driver->chars_in_buffer(priv->tty);
+       return tty_chars_in_buffer(priv->tty);
 }
 
 /* Wait (sleep) until underlaying hardware finished transmission
@@ -93,10 +93,8 @@ static void irtty_wait_until_sent(struct sir_dev *dev)
        IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;);
 
        tty = priv->tty;
-       if (tty->driver->wait_until_sent) {
-               lock_kernel();
-               tty->driver->wait_until_sent(tty, msecs_to_jiffies(100));
-               unlock_kernel();
+       if (tty->ops->wait_until_sent) {
+               tty->ops->wait_until_sent(tty, msecs_to_jiffies(100));
        }
        else {
                msleep(USBSERIAL_TX_DONE_DELAY);
@@ -125,48 +123,14 @@ static int irtty_change_speed(struct sir_dev *dev, unsigned speed)
 
        tty = priv->tty;
 
-       lock_kernel();
+       mutex_lock(&tty->termios_mutex);
        old_termios = *(tty->termios);
        cflag = tty->termios->c_cflag;
-
-       cflag &= ~CBAUD;
-
-       IRDA_DEBUG(2, "%s(), Setting speed to %d\n", __FUNCTION__, speed);
-
-       switch (speed) {
-       case 1200:
-               cflag |= B1200;
-               break;
-       case 2400:
-               cflag |= B2400;
-               break;
-       case 4800:
-               cflag |= B4800;
-               break;
-       case 19200:
-               cflag |= B19200;
-               break;
-       case 38400:
-               cflag |= B38400;
-               break;
-       case 57600:
-               cflag |= B57600;
-               break;
-       case 115200:
-               cflag |= B115200;
-               break;
-       case 9600:
-       default:
-               cflag |= B9600;
-               break;
-       }       
-
-       tty->termios->c_cflag = cflag;
-       if (tty->driver->set_termios)
-               tty->driver->set_termios(tty, &old_termios);
-       unlock_kernel();
-
+       tty_encode_baud_rate(tty, speed, speed);
+       if (tty->ops->set_termios)
+               tty->ops->set_termios(tty, &old_termios);
        priv->io.speed = speed;
+       mutex_unlock(&tty->termios_mutex);
 
        return 0;
 }
@@ -202,8 +166,8 @@ static int irtty_set_dtr_rts(struct sir_dev *dev, int dtr, int rts)
         * This function is not yet defined for all tty driver, so
         * let's be careful... Jean II
         */
-       IRDA_ASSERT(priv->tty->driver->tiocmset != NULL, return -1;);
-       priv->tty->driver->tiocmset(priv->tty, NULL, set, clear);
+       IRDA_ASSERT(priv->tty->ops->tiocmset != NULL, return -1;);
+       priv->tty->ops->tiocmset(priv->tty, NULL, set, clear);
 
        return 0;
 }
@@ -225,17 +189,13 @@ static int irtty_do_write(struct sir_dev *dev, const unsigned char *ptr, size_t
        IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
 
        tty = priv->tty;
-       if (!tty->driver->write)
+       if (!tty->ops->write)
                return 0;
        tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
-       if (tty->driver->write_room) {
-               writelen = tty->driver->write_room(tty);
-               if (writelen > len)
-                       writelen = len;
-       }
-       else
+       writelen = tty_write_room(tty);
+       if (writelen > len)
                writelen = len;
-       return tty->driver->write(tty, ptr, writelen);
+       return tty->ops->write(tty, ptr, writelen);
 }
 
 /* ------------------------------------------------------- */
@@ -321,7 +281,7 @@ static inline void irtty_stop_receiver(struct tty_struct *tty, int stop)
        struct ktermios old_termios;
        int cflag;
 
-       lock_kernel();
+       mutex_lock(&tty->termios_mutex);
        old_termios = *(tty->termios);
        cflag = tty->termios->c_cflag;
        
@@ -331,9 +291,9 @@ static inline void irtty_stop_receiver(struct tty_struct *tty, int stop)
                cflag |= CREAD;
 
        tty->termios->c_cflag = cflag;
-       if (tty->driver->set_termios)
-               tty->driver->set_termios(tty, &old_termios);
-       unlock_kernel();
+       if (tty->ops->set_termios)
+               tty->ops->set_termios(tty, &old_termios);
+       mutex_unlock(&tty->termios_mutex);
 }
 
 /*****************************************************************/
@@ -359,8 +319,8 @@ static int irtty_start_dev(struct sir_dev *dev)
 
        tty = priv->tty;
 
-       if (tty->driver->start)
-               tty->driver->start(tty);
+       if (tty->ops->start)
+               tty->ops->start(tty);
        /* Make sure we can receive more data */
        irtty_stop_receiver(tty, FALSE);
 
@@ -388,8 +348,8 @@ static int irtty_stop_dev(struct sir_dev *dev)
 
        /* Make sure we don't receive more data */
        irtty_stop_receiver(tty, TRUE);
-       if (tty->driver->stop)
-               tty->driver->stop(tty);
+       if (tty->ops->stop)
+               tty->ops->stop(tty);
 
        mutex_unlock(&irtty_mutex);
 
@@ -483,11 +443,10 @@ static int irtty_open(struct tty_struct *tty)
 
        /* stop the underlying  driver */
        irtty_stop_receiver(tty, TRUE);
-       if (tty->driver->stop)
-               tty->driver->stop(tty);
+       if (tty->ops->stop)
+               tty->ops->stop(tty);
 
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       tty_driver_flush_buffer(tty);
        
        /* apply mtt override */
        sir_tty_drv.qos_mtt_bits = qos_mtt_bits;
@@ -564,8 +523,8 @@ static void irtty_close(struct tty_struct *tty)
        /* Stop tty */
        irtty_stop_receiver(tty, TRUE);
        tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
-       if (tty->driver->stop)
-               tty->driver->stop(tty);
+       if (tty->ops->stop)
+               tty->ops->stop(tty);
 
        kfree(priv);
 
index 93916cf33f295604e939d02d2b7a1f0bfef28e66..ad92d3ff1c4093ff6ea8281c430374ab26ff3ac2 100644 (file)
@@ -464,7 +464,7 @@ static void mcs_unwrap_fir(struct mcs_cb *mcs, __u8 *buf, int len)
        }
 
        fcs = ~(crc32_le(~0, buf, new_len));
-       if(fcs != le32_to_cpu(get_unaligned((__le32 *)(buf+new_len)))) {
+       if(fcs != get_unaligned_le32(buf + new_len)) {
                IRDA_ERROR("crc error calc 0x%x len %d\n", fcs, new_len);
                mcs->stats.rx_errors++;
                mcs->stats.rx_crc_errors++;
index e59c485bc497f0f98054b6fea0424c320c3a3dfb..0519637827497c0e3e978a09ac5b0628df0d7ba3 100644 (file)
@@ -329,7 +329,7 @@ static void fir_eof(struct stir_cb *stir)
        }
 
        fcs = ~(crc32_le(~0, rx_buff->data, len));
-       if (fcs != le32_to_cpu(get_unaligned((__le32 *)(rx_buff->data+len)))) {
+       if (fcs != get_unaligned_le32(rx_buff->data + len)) {
                pr_debug("crc error calc 0x%x len %d\n", fcs, len);
                stir->stats.rx_errors++;
                stir->stats.rx_crc_errors++;
index acd082a96a4f2b6dd986c956552adae410d48065..d15e00b8591e173aeb55a08623a773ced53b6d8f 100644 (file)
@@ -1674,13 +1674,12 @@ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (vlsi_proc_root != NULL) {
                struct proc_dir_entry *ent;
 
-               ent = create_proc_entry(ndev->name, S_IFREG|S_IRUGO, vlsi_proc_root);
+               ent = proc_create_data(ndev->name, S_IFREG|S_IRUGO,
+                                      vlsi_proc_root, VLSI_PROC_FOPS, ndev);
                if (!ent) {
                        IRDA_WARNING("%s: failed to create proc entry\n",
                                     __FUNCTION__);
                } else {
-                       ent->data = ndev;
-                       ent->proc_fops = VLSI_PROC_FOPS;
                        ent->size = 0;
                }
                idev->proc_entry = ent;
index 6fda0af9d0a6e068a3b6d55cf62db88312403f57..95e87a2f8896f97ca5110613fdcd2a6527ccfc5f 100644 (file)
@@ -188,7 +188,8 @@ int mlx4_cq_resize(struct mlx4_dev *dev, struct mlx4_cq *cq,
 EXPORT_SYMBOL_GPL(mlx4_cq_resize);
 
 int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
-                 struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq)
+                 struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq,
+                 int collapsed)
 {
        struct mlx4_priv *priv = mlx4_priv(dev);
        struct mlx4_cq_table *cq_table = &priv->cq_table;
@@ -224,6 +225,7 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
        cq_context = mailbox->buf;
        memset(cq_context, 0, sizeof *cq_context);
 
+       cq_context->flags           = cpu_to_be32(!!collapsed << 18);
        cq_context->logsize_usrpage = cpu_to_be32((ilog2(nent) << 24) | uar->index);
        cq_context->comp_eqn        = priv->eq_table.eq[MLX4_EQ_COMP].eqn;
        cq_context->log_page_size   = mtt->page_shift - MLX4_ICM_PAGE_SHIFT;
index 79b317b88c86b13105124b64a4754330839b753e..cb46446b2691b88a7db70ce08a482f9a09696e5a 100644 (file)
@@ -607,15 +607,9 @@ EXPORT_SYMBOL_GPL(mlx4_fmr_enable);
 void mlx4_fmr_unmap(struct mlx4_dev *dev, struct mlx4_fmr *fmr,
                    u32 *lkey, u32 *rkey)
 {
-       u32 key;
-
        if (!fmr->maps)
                return;
 
-       key = key_to_hw_index(fmr->mr.key);
-       key &= dev->caps.num_mpts - 1;
-       *lkey = *rkey = fmr->mr.key = hw_index_to_key(key);
-
        fmr->maps = 0;
 
        *(u8 *) fmr->mpt = MLX4_MPT_STATUS_SW;
index cead81e80f0c84dfcc443e0eb1466f09664f0f71..ef63c8d2bd7e4ae550a2f2add91b9327b1e6a40a 100644 (file)
@@ -2437,7 +2437,7 @@ static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev)
        int status;
 
        segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO6);
-       if (unlikely(IS_ERR(segs)))
+       if (IS_ERR(segs))
                goto drop;
 
        while (segs) {
index f023d5b67e6efcc38d1673ef56b9de8536371392..f1a52def1241a387c28ed6f5a045b839df8f994f 100644 (file)
@@ -158,6 +158,9 @@ ppp_asynctty_open(struct tty_struct *tty)
        struct asyncppp *ap;
        int err;
 
+       if (tty->ops->write == NULL)
+               return -EOPNOTSUPP;
+
        err = -ENOMEM;
        ap = kzalloc(sizeof(*ap), GFP_KERNEL);
        if (!ap)
@@ -358,9 +361,7 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,
        if (!skb_queue_empty(&ap->rqueue))
                tasklet_schedule(&ap->tsk);
        ap_put(ap);
-       if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
-           && tty->driver->unthrottle)
-               tty->driver->unthrottle(tty);
+       tty_unthrottle(tty);
 }
 
 static void
@@ -676,7 +677,7 @@ ppp_async_push(struct asyncppp *ap)
                if (!tty_stuffed && ap->optr < ap->olim) {
                        avail = ap->olim - ap->optr;
                        set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
-                       sent = tty->driver->write(tty, ap->optr, avail);
+                       sent = tty->ops->write(tty, ap->optr, avail);
                        if (sent < 0)
                                goto flush;     /* error, e.g. loss of CD */
                        ap->optr += sent;
index 0d80fa54671963a002540d29eefdcaf042c7aa8d..b8f0369a71e777a30b8a52897184a6cca3a2cb4a 100644 (file)
@@ -207,6 +207,9 @@ ppp_sync_open(struct tty_struct *tty)
        struct syncppp *ap;
        int err;
 
+       if (tty->ops->write == NULL)
+               return -EOPNOTSUPP;
+
        ap = kzalloc(sizeof(*ap), GFP_KERNEL);
        err = -ENOMEM;
        if (!ap)
@@ -398,9 +401,7 @@ ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,
        if (!skb_queue_empty(&ap->rqueue))
                tasklet_schedule(&ap->tsk);
        sp_put(ap);
-       if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
-           && tty->driver->unthrottle)
-               tty->driver->unthrottle(tty);
+       tty_unthrottle(tty);
 }
 
 static void
@@ -653,7 +654,7 @@ ppp_sync_push(struct syncppp *ap)
                        tty_stuffed = 0;
                if (!tty_stuffed && ap->tpkt) {
                        set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
-                       sent = tty->driver->write(tty, ap->tpkt->data, ap->tpkt->len);
+                       sent = tty->ops->write(tty, ap->tpkt->data, ap->tpkt->len);
                        if (sent < 0)
                                goto flush;     /* error, e.g. loss of CD */
                        if (sent < ap->tpkt->len) {
index 4fad4ddb35048419beb3484ea4d14acd4ac6b241..58a26a47af29a1ee3764968dda5e7497752c9e7a 100644 (file)
@@ -1052,11 +1052,9 @@ static int __init pppoe_proc_init(void)
 {
        struct proc_dir_entry *p;
 
-       p = create_proc_entry("pppoe", S_IRUGO, init_net.proc_net);
+       p = proc_net_fops_create(&init_net, "pppoe", S_IRUGO, &pppoe_seq_fops);
        if (!p)
                return -ENOMEM;
-
-       p->proc_fops = &pppoe_seq_fops;
        return 0;
 }
 #else /* CONFIG_PROC_FS */
index 3d10ca050b7991b9f53cf4a6cc3d5adb873137aa..244d7830c92aac88486981f7ec52b3d3b141631f 100644 (file)
@@ -2469,12 +2469,12 @@ static int __init pppol2tp_init(void)
                goto out_unregister_pppol2tp_proto;
 
 #ifdef CONFIG_PROC_FS
-       pppol2tp_proc = create_proc_entry("pppol2tp", 0, init_net.proc_net);
+       pppol2tp_proc = proc_net_fops_create(&init_net, "pppol2tp", 0,
+                                            &pppol2tp_proc_fops);
        if (!pppol2tp_proc) {
                err = -ENOMEM;
                goto out_unregister_pppox_proto;
        }
-       pppol2tp_proc->proc_fops = &pppol2tp_proc_fops;
 #endif /* CONFIG_PROC_FS */
        printk(KERN_INFO "PPPoL2TP kernel driver, %s\n",
               PPPOL2TP_DRV_VERSION);
index 5a55ede352f4bc79dbceb5ee73bc2a6c0afb59d6..84af68fdb6c2b08ca53bc2357a5db17959825cee 100644 (file)
@@ -396,14 +396,14 @@ static void sl_encaps(struct slip *sl, unsigned char *icp, int len)
 
        /* Order of next two lines is *very* important.
         * When we are sending a little amount of data,
-        * the transfer may be completed inside driver.write()
+        * the transfer may be completed inside the ops->write()
         * routine, because it's running with interrupts enabled.
         * In this case we *never* got WRITE_WAKEUP event,
         * if we did not request it before write operation.
         *       14 Oct 1994  Dmitry Gorodchanin.
         */
        sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
-       actual = sl->tty->driver->write(sl->tty, sl->xbuff, count);
+       actual = sl->tty->ops->write(sl->tty, sl->xbuff, count);
 #ifdef SL_CHECK_TRANSMIT
        sl->dev->trans_start = jiffies;
 #endif
@@ -437,7 +437,7 @@ static void slip_write_wakeup(struct tty_struct *tty)
                return;
        }
 
-       actual = tty->driver->write(tty, sl->xhead, sl->xleft);
+       actual = tty->ops->write(tty, sl->xhead, sl->xleft);
        sl->xleft -= actual;
        sl->xhead += actual;
 }
@@ -462,7 +462,7 @@ static void sl_tx_timeout(struct net_device *dev)
                }
                printk(KERN_WARNING "%s: transmit timed out, %s?\n",
                        dev->name,
-                       (sl->tty->driver->chars_in_buffer(sl->tty) || sl->xleft) ?
+                       (tty_chars_in_buffer(sl->tty) || sl->xleft) ?
                                "bad line quality" : "driver error");
                sl->xleft = 0;
                sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
@@ -830,6 +830,9 @@ static int slip_open(struct tty_struct *tty)
        if (!capable(CAP_NET_ADMIN))
                return -EPERM;
 
+       if (tty->ops->write == NULL)
+               return -EOPNOTSUPP;
+
        /* RTnetlink lock is misused here to serialize concurrent
           opens of slip channels. There are better ways, but it is
           the simplest one.
@@ -1432,7 +1435,7 @@ static void sl_outfill(unsigned long sls)
                        /* put END into tty queue. Is it right ??? */
                        if (!netif_queue_stopped(sl->dev)) {
                                /* if device busy no outfill */
-                               sl->tty->driver->write(sl->tty, &s, 1);
+                               sl->tty->ops->write(sl->tty, &s, 1);
                        }
                } else
                        set_bit(SLF_OUTWAIT, &sl->flags);
index e83b166aa6b9a53aeeb00a70224d10e46660f638..432e837a17607e323021da0d98dccdc310b1705e 100644 (file)
@@ -649,7 +649,7 @@ static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
                DBG("%d 0x%x 0x%x\n", data[0], data[1], data[2]);
        }
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!capable(CAP_SYS_RAWIO))
                return -EPERM;
 
        switch (data[0]) {
index e3f74c9f78bd848f1e61aa6647f7109e7282fd7c..b66c75e3b8a1f6428b4d9f0409e6f611421bb923 100644 (file)
@@ -4361,7 +4361,7 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb)
        }
 
        segs = skb_gso_segment(skb, tp->dev->features & ~NETIF_F_TSO);
-       if (unlikely(IS_ERR(segs)))
+       if (IS_ERR(segs))
                goto tg3_tso_bug_end;
 
        do {
index 6c6fc325c8f96856a7a511a17b163bce3b54d5ab..bc30c6e8fea2c69779746c67b250dc767918453f 100644 (file)
 static char version[] __devinitdata = "de4x5.c:V0.546 2001/02/22 davies@maniac.ultranet.com\n";
 
 #define c_char const char
-#define TWIDDLE(a) (u_short)le16_to_cpu(get_unaligned((__le16 *)(a)))
 
 /*
 ** MII Information
@@ -4405,7 +4404,7 @@ srom_infoleaf_info(struct net_device *dev)
        }
     }
 
-    lp->infoleaf_offset = TWIDDLE(p+1);
+       lp->infoleaf_offset = get_unaligned_le16(p + 1);
 
     return 0;
 }
@@ -4476,7 +4475,7 @@ srom_exec(struct net_device *dev, u_char *p)
 
     while (count--) {
        gep_wr(((lp->chipset==DC21140) && (lp->ibn!=5) ?
-                                                  *p++ : TWIDDLE(w++)), dev);
+                                                  *p++ : get_unaligned_le16(w++)), dev);
        mdelay(2);                          /* 2ms per action */
     }
 
@@ -4711,10 +4710,10 @@ type1_infoblock(struct net_device *dev, u_char count, u_char *p)
        lp->active = *p++;
        lp->phy[lp->active].gep = (*p ? p : NULL); p += (*p + 1);
        lp->phy[lp->active].rst = (*p ? p : NULL); p += (*p + 1);
-       lp->phy[lp->active].mc  = TWIDDLE(p); p += 2;
-       lp->phy[lp->active].ana = TWIDDLE(p); p += 2;
-       lp->phy[lp->active].fdx = TWIDDLE(p); p += 2;
-       lp->phy[lp->active].ttm = TWIDDLE(p);
+       lp->phy[lp->active].mc  = get_unaligned_le16(p); p += 2;
+       lp->phy[lp->active].ana = get_unaligned_le16(p); p += 2;
+       lp->phy[lp->active].fdx = get_unaligned_le16(p); p += 2;
+       lp->phy[lp->active].ttm = get_unaligned_le16(p);
        return 0;
     } else if ((lp->media == INIT) && (lp->timeout < 0)) {
         lp->ibn = 1;
@@ -4751,16 +4750,16 @@ type2_infoblock(struct net_device *dev, u_char count, u_char *p)
        lp->infoblock_media = (*p) & MEDIA_CODE;
 
         if ((*p++) & EXT_FIELD) {
-           lp->cache.csr13 = TWIDDLE(p); p += 2;
-           lp->cache.csr14 = TWIDDLE(p); p += 2;
-           lp->cache.csr15 = TWIDDLE(p); p += 2;
+           lp->cache.csr13 = get_unaligned_le16(p); p += 2;
+           lp->cache.csr14 = get_unaligned_le16(p); p += 2;
+           lp->cache.csr15 = get_unaligned_le16(p); p += 2;
        } else {
            lp->cache.csr13 = CSR13;
            lp->cache.csr14 = CSR14;
            lp->cache.csr15 = CSR15;
        }
-        lp->cache.gepc = ((s32)(TWIDDLE(p)) << 16); p += 2;
-        lp->cache.gep  = ((s32)(TWIDDLE(p)) << 16);
+        lp->cache.gepc = ((s32)(get_unaligned_le16(p)) << 16); p += 2;
+        lp->cache.gep  = ((s32)(get_unaligned_le16(p)) << 16);
        lp->infoblock_csr6 = OMR_SIA;
        lp->useMII = false;
 
@@ -4792,10 +4791,10 @@ type3_infoblock(struct net_device *dev, u_char count, u_char *p)
        if (MOTO_SROM_BUG) lp->active = 0;
        lp->phy[lp->active].gep = (*p ? p : NULL); p += (2 * (*p) + 1);
        lp->phy[lp->active].rst = (*p ? p : NULL); p += (2 * (*p) + 1);
-       lp->phy[lp->active].mc  = TWIDDLE(p); p += 2;
-       lp->phy[lp->active].ana = TWIDDLE(p); p += 2;
-       lp->phy[lp->active].fdx = TWIDDLE(p); p += 2;
-       lp->phy[lp->active].ttm = TWIDDLE(p); p += 2;
+       lp->phy[lp->active].mc  = get_unaligned_le16(p); p += 2;
+       lp->phy[lp->active].ana = get_unaligned_le16(p); p += 2;
+       lp->phy[lp->active].fdx = get_unaligned_le16(p); p += 2;
+       lp->phy[lp->active].ttm = get_unaligned_le16(p); p += 2;
        lp->phy[lp->active].mci = *p;
        return 0;
     } else if ((lp->media == INIT) && (lp->timeout < 0)) {
@@ -4835,8 +4834,8 @@ type4_infoblock(struct net_device *dev, u_char count, u_char *p)
         lp->cache.csr13 = CSR13;              /* Hard coded defaults */
        lp->cache.csr14 = CSR14;
        lp->cache.csr15 = CSR15;
-        lp->cache.gepc = ((s32)(TWIDDLE(p)) << 16); p += 2;
-        lp->cache.gep  = ((s32)(TWIDDLE(p)) << 16); p += 2;
+        lp->cache.gepc = ((s32)(get_unaligned_le16(p)) << 16); p += 2;
+        lp->cache.gep  = ((s32)(get_unaligned_le16(p)) << 16); p += 2;
        csr6 = *p++;
        flags = *p++;
 
index 9fb8d7f079943c07c9bca5f982a7cc26ea2c4663..f5f33b3eb067ad98a4105c41b5a7adea6739ded4 100644 (file)
@@ -1017,4 +1017,4 @@ struct de4x5_ioctl {
 #define DE4X5_SET_OMR           0x0d /* Set the OMR Register contents */
 #define DE4X5_GET_REG           0x0e /* Get the DE4X5 Registers */
 
-#define MOTO_SROM_BUG    ((lp->active == 8) && (((le32_to_cpu(get_unaligned(((__le32 *)dev->dev_addr))))&0x00ffffff)==0x3e0008))
+#define MOTO_SROM_BUG    (lp->active == 8 && (get_unaligned_le32(dev->dev_addr) & 0x00ffffff) == 0x3e0008)
index 908422f2f320369e5523ae015cb3dac280fa8782..92c68a22f16b50ab66d59a4fc7ac4e0fce3a1c2b 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/pci.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/unaligned.h>
 
 
 
@@ -304,11 +305,7 @@ enum t21143_csr6_bits {
 
 #define RUN_AT(x) (jiffies + (x))
 
-#if defined(__i386__)                  /* AKA get_unaligned() */
-#define get_u16(ptr) (*(u16 *)(ptr))
-#else
-#define get_u16(ptr) (((u8*)(ptr))[0] + (((u8*)(ptr))[1]<<8))
-#endif
+#define get_u16(ptr) get_unaligned_le16((ptr))
 
 struct medialeaf {
        u8 type;
index fa1c1c329a2d890a19d1b225a7dac503ac5e740e..f9d13fa05d64dc010fcce435b237db7360df60af 100644 (file)
@@ -327,8 +327,8 @@ static void tulip_up(struct net_device *dev)
        tp->dirty_rx = tp->dirty_tx = 0;
 
        if (tp->flags & MC_HASH_ONLY) {
-               u32 addr_low = le32_to_cpu(get_unaligned((__le32 *)dev->dev_addr));
-               u32 addr_high = le16_to_cpu(get_unaligned((__le16 *)(dev->dev_addr+4)));
+               u32 addr_low = get_unaligned_le32(dev->dev_addr);
+               u32 addr_high = get_unaligned_le16(dev->dev_addr + 4);
                if (tp->chip_id == AX88140) {
                        iowrite32(0, ioaddr + CSR13);
                        iowrite32(addr_low,  ioaddr + CSR14);
@@ -1437,13 +1437,13 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
                        do
                                value = ioread32(ioaddr + CSR9);
                        while (value < 0  && --boguscnt > 0);
-                       put_unaligned(cpu_to_le16(value), ((__le16*)dev->dev_addr) + i);
+                       put_unaligned_le16(value, ((__le16 *)dev->dev_addr) + i);
                        sum += value & 0xffff;
                }
        } else if (chip_idx == COMET) {
                /* No need to read the EEPROM. */
-               put_unaligned(cpu_to_le32(ioread32(ioaddr + 0xA4)), (__le32 *)dev->dev_addr);
-               put_unaligned(cpu_to_le16(ioread32(ioaddr + 0xA8)), (__le16 *)(dev->dev_addr + 4));
+               put_unaligned_le32(ioread32(ioaddr + 0xA4), dev->dev_addr);
+               put_unaligned_le16(ioread32(ioaddr + 0xA8), dev->dev_addr + 4);
                for (i = 0; i < 6; i ++)
                        sum += dev->dev_addr[i];
        } else {
index 63abfd72542d118c7a8b93f25cbd5ed3098337ca..e03eef2f2282088c3366356e80979ad52d538661 100644 (file)
@@ -178,6 +178,20 @@ static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char signal)
        CPC_TTY_UNLOCK(card,flags); 
 }
 
+
+static const struct tty_operations pc300_ops = {
+       .open = cpc_tty_open,
+       .close = cpc_tty_close,
+       .write = cpc_tty_write,
+       .write_room = cpc_tty_write_room,
+       .chars_in_buffer = cpc_tty_chars_in_buffer,
+       .tiocmset = pc300_tiocmset,
+       .tiocmget = pc300_tiocmget,
+       .flush_buffer = cpc_tty_flush_buffer,
+       .hangup = cpc_tty_hangup,
+};
+
+
 /*
  * PC300 TTY initialization routine
  *
@@ -225,15 +239,7 @@ void cpc_tty_init(pc300dev_t *pc300dev)
                serial_drv.flags = TTY_DRIVER_REAL_RAW;
 
                /* interface routines from the upper tty layer to the tty driver */
-               serial_drv.open = cpc_tty_open;
-               serial_drv.close = cpc_tty_close;
-               serial_drv.write = cpc_tty_write; 
-               serial_drv.write_room = cpc_tty_write_room; 
-               serial_drv.chars_in_buffer = cpc_tty_chars_in_buffer; 
-               serial_drv.tiocmset = pc300_tiocmset;
-               serial_drv.tiocmget = pc300_tiocmget;
-               serial_drv.flush_buffer = cpc_tty_flush_buffer; 
-               serial_drv.hangup = cpc_tty_hangup;
+               tty_set_operations(&serial_drv, &pc300_ops);
 
                /* register the TTY driver */
                if (tty_register_driver(&serial_drv)) { 
index 0f8aca8a4d4331b484226f749f6f33012c1a9cf3..249e18053d5fa4a2d6e29a60e33878bbe1f78c90 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/module.h>
 
 #include <asm/system.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/bitops.h>
 #include <linux/string.h>
 #include <linux/mm.h>
@@ -95,7 +95,7 @@ static struct x25_asy *x25_asy_alloc(void)
                        x25_asy_devs[i] = dev;
                        return sl;
                } else {
-                       printk("x25_asy_alloc() - register_netdev() failure.\n");
+                       printk(KERN_WARNING "x25_asy_alloc() - register_netdev() failure.\n");
                        free_netdev(dev);
                }
        }
@@ -112,23 +112,22 @@ static void x25_asy_free(struct x25_asy *sl)
        kfree(sl->xbuff);
        sl->xbuff = NULL;
 
-       if (!test_and_clear_bit(SLF_INUSE, &sl->flags)) {
-               printk("%s: x25_asy_free for already free unit.\n", sl->dev->name);
-       }
+       if (!test_and_clear_bit(SLF_INUSE, &sl->flags))
+               printk(KERN_ERR "%s: x25_asy_free for already free unit.\n",
+                       sl->dev->name);
 }
 
 static int x25_asy_change_mtu(struct net_device *dev, int newmtu)
 {
        struct x25_asy *sl = dev->priv;
        unsigned char *xbuff, *rbuff;
-       int len = 2* newmtu;
+       int len = 2 * newmtu;
 
        xbuff = kmalloc(len + 4, GFP_ATOMIC);
        rbuff = kmalloc(len + 4, GFP_ATOMIC);
 
-       if (xbuff == NULL || rbuff == NULL)  
-       {
-               printk("%s: unable to grow X.25 buffers, MTU change cancelled.\n",
+       if (xbuff == NULL || rbuff == NULL) {
+               printk(KERN_WARNING "%s: unable to grow X.25 buffers, MTU change cancelled.\n",
                       dev->name);
                kfree(xbuff);
                kfree(rbuff);
@@ -193,25 +192,23 @@ static void x25_asy_bump(struct x25_asy *sl)
        int err;
 
        count = sl->rcount;
-       sl->stats.rx_bytes+=count;
-       
+       sl->stats.rx_bytes += count;
+
        skb = dev_alloc_skb(count+1);
-       if (skb == NULL)  
-       {
-               printk("%s: memory squeeze, dropping packet.\n", sl->dev->name);
+       if (skb == NULL) {
+               printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n",
+                       sl->dev->name);
                sl->stats.rx_dropped++;
                return;
        }
-       skb_push(skb,1);        /* LAPB internal control */
-       memcpy(skb_put(skb,count), sl->rbuff, count);
+       skb_push(skb, 1);       /* LAPB internal control */
+       memcpy(skb_put(skb, count), sl->rbuff, count);
        skb->protocol = x25_type_trans(skb, sl->dev);
-       if((err=lapb_data_received(skb->dev, skb))!=LAPB_OK)
-       {
+       err = lapb_data_received(skb->dev, skb);
+       if (err != LAPB_OK) {
                kfree_skb(skb);
-               printk(KERN_DEBUG "x25_asy: data received err - %d\n",err);
-       }
-       else
-       {
+               printk(KERN_DEBUG "x25_asy: data received err - %d\n", err);
+       } else {
                netif_rx(skb);
                sl->dev->last_rx = jiffies;
                sl->stats.rx_packets++;
@@ -224,10 +221,11 @@ static void x25_asy_encaps(struct x25_asy *sl, unsigned char *icp, int len)
        unsigned char *p;
        int actual, count, mtu = sl->dev->mtu;
 
-       if (len > mtu) 
-       {               /* Sigh, shouldn't occur BUT ... */
+       if (len > mtu) {
+               /* Sigh, shouldn't occur BUT ... */
                len = mtu;
-               printk ("%s: truncating oversized transmit packet!\n", sl->dev->name);
+               printk(KERN_DEBUG "%s: truncating oversized transmit packet!\n",
+                                       sl->dev->name);
                sl->stats.tx_dropped++;
                x25_asy_unlock(sl);
                return;
@@ -245,7 +243,7 @@ static void x25_asy_encaps(struct x25_asy *sl, unsigned char *icp, int len)
         *       14 Oct 1994  Dmitry Gorodchanin.
         */
        sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
-       actual = sl->tty->driver->write(sl->tty, sl->xbuff, count);
+       actual = sl->tty->ops->write(sl->tty, sl->xbuff, count);
        sl->xleft = count - actual;
        sl->xhead = sl->xbuff + actual;
        /* VSV */
@@ -265,8 +263,7 @@ static void x25_asy_write_wakeup(struct tty_struct *tty)
        if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev))
                return;
 
-       if (sl->xleft <= 0)  
-       {
+       if (sl->xleft <= 0) {
                /* Now serial buffer is almost free & we can start
                 * transmission of another packet */
                sl->stats.tx_packets++;
@@ -275,14 +272,14 @@ static void x25_asy_write_wakeup(struct tty_struct *tty)
                return;
        }
 
-       actual = tty->driver->write(tty, sl->xhead, sl->xleft);
+       actual = tty->ops->write(tty, sl->xhead, sl->xleft);
        sl->xleft -= actual;
        sl->xhead += actual;
 }
 
 static void x25_asy_timeout(struct net_device *dev)
 {
-       struct x25_asy *sl = (struct x25_asy*)(dev->priv);
+       struct x25_asy *sl = dev->priv;
 
        spin_lock(&sl->lock);
        if (netif_queue_stopped(dev)) {
@@ -290,7 +287,7 @@ static void x25_asy_timeout(struct net_device *dev)
                 *      14 Oct 1994 Dmitry Gorodchanin.
                 */
                printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
-                      (sl->tty->driver->chars_in_buffer(sl->tty) || sl->xleft) ?
+                      (tty_chars_in_buffer(sl->tty) || sl->xleft) ?
                       "bad line quality" : "driver error");
                sl->xleft = 0;
                sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
@@ -303,31 +300,34 @@ static void x25_asy_timeout(struct net_device *dev)
 
 static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-       struct x25_asy *sl = (struct x25_asy*)(dev->priv);
+       struct x25_asy *sl = dev->priv;
        int err;
 
        if (!netif_running(sl->dev)) {
-               printk("%s: xmit call when iface is down\n", dev->name);
+               printk(KERN_ERR "%s: xmit call when iface is down\n",
+                       dev->name);
                kfree_skb(skb);
                return 0;
        }
-       
-       switch(skb->data[0])
-       {
-               case 0x00:break;
-               case 0x01: /* Connection request .. do nothing */
-                       if((err=lapb_connect_request(dev))!=LAPB_OK)
-                               printk(KERN_ERR "x25_asy: lapb_connect_request error - %d\n", err);
-                       kfree_skb(skb);
-                       return 0;
-               case 0x02: /* Disconnect request .. do nothing - hang up ?? */
-                       if((err=lapb_disconnect_request(dev))!=LAPB_OK)
-                               printk(KERN_ERR "x25_asy: lapb_disconnect_request error - %d\n", err);
-               default:
-                       kfree_skb(skb);
-                       return  0;
+
+       switch (skb->data[0]) {
+       case 0x00:
+               break;
+       case 0x01: /* Connection request .. do nothing */
+               err = lapb_connect_request(dev);
+               if (err != LAPB_OK)
+                       printk(KERN_ERR "x25_asy: lapb_connect_request error - %d\n", err);
+               kfree_skb(skb);
+               return 0;
+       case 0x02: /* Disconnect request .. do nothing - hang up ?? */
+               err = lapb_disconnect_request(dev);
+               if (err != LAPB_OK)
+                       printk(KERN_ERR "x25_asy: lapb_disconnect_request error - %d\n", err);
+       default:
+               kfree_skb(skb);
+               return  0;
        }
-       skb_pull(skb,1);        /* Remove control byte */
+       skb_pull(skb, 1);       /* Remove control byte */
        /*
         * If we are busy already- too bad.  We ought to be able
         * to queue things at this point, to allow for a little
@@ -338,10 +338,10 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
         * So, no queues !
         *        14 Oct 1994  Dmitry Gorodchanin.
         */
-       
-       if((err=lapb_data_request(dev,skb))!=LAPB_OK)
-       {
-               printk(KERN_ERR "lapbeth: lapb_data_request error - %d\n", err);
+
+       err = lapb_data_request(dev, skb);
+       if (err != LAPB_OK) {
+               printk(KERN_ERR "x25_asy: lapb_data_request error - %d\n", err);
                kfree_skb(skb);
                return 0;
        }
@@ -357,7 +357,7 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
  *     Called when I frame data arrives. We did the work above - throw it
  *     at the net layer.
  */
-  
+
 static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb)
 {
        skb->dev->last_rx = jiffies;
@@ -369,24 +369,22 @@ static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb)
  *     busy cases too well. Its tricky to see how to do this nicely -
  *     perhaps lapb should allow us to bounce this ?
  */
+
 static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb)
 {
-       struct x25_asy *sl=dev->priv;
-       
+       struct x25_asy *sl = dev->priv;
+
        spin_lock(&sl->lock);
-       if (netif_queue_stopped(sl->dev) || sl->tty == NULL)
-       {
+       if (netif_queue_stopped(sl->dev) || sl->tty == NULL) {
                spin_unlock(&sl->lock);
                printk(KERN_ERR "x25_asy: tbusy drop\n");
                kfree_skb(skb);
                return;
        }
        /* We were not busy, so we are now... :-) */
-       if (skb != NULL) 
-       {
+       if (skb != NULL) {
                x25_asy_lock(sl);
-               sl->stats.tx_bytes+=skb->len;
+               sl->stats.tx_bytes += skb->len;
                x25_asy_encaps(sl, skb->data, skb->len);
                dev_kfree_skb(skb);
        }
@@ -396,15 +394,16 @@ static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb)
 /*
  *     LAPB connection establish/down information.
  */
+
 static void x25_asy_connected(struct net_device *dev, int reason)
 {
        struct x25_asy *sl = dev->priv;
        struct sk_buff *skb;
        unsigned char *ptr;
 
-       if ((skb = dev_alloc_skb(1)) == NULL) {
-               printk(KERN_ERR "lapbeth: out of memory\n");
+       skb = dev_alloc_skb(1);
+       if (skb == NULL) {
+               printk(KERN_ERR "x25_asy: out of memory\n");
                return;
        }
 
@@ -422,7 +421,8 @@ static void x25_asy_disconnected(struct net_device *dev, int reason)
        struct sk_buff *skb;
        unsigned char *ptr;
 
-       if ((skb = dev_alloc_skb(1)) == NULL) {
+       skb = dev_alloc_skb(1);
+       if (skb == NULL) {
                printk(KERN_ERR "x25_asy: out of memory\n");
                return;
        }
@@ -449,7 +449,7 @@ static struct lapb_register_struct x25_asy_callbacks = {
 /* Open the low-level part of the X.25 channel. Easy! */
 static int x25_asy_open(struct net_device *dev)
 {
-       struct x25_asy *sl = (struct x25_asy*)(dev->priv);
+       struct x25_asy *sl = dev->priv;
        unsigned long len;
        int err;
 
@@ -466,13 +466,11 @@ static int x25_asy_open(struct net_device *dev)
        len = dev->mtu * 2;
 
        sl->rbuff = kmalloc(len + 4, GFP_KERNEL);
-       if (sl->rbuff == NULL)   {
+       if (sl->rbuff == NULL)
                goto norbuff;
-       }
        sl->xbuff = kmalloc(len + 4, GFP_KERNEL);
-       if (sl->xbuff == NULL)   {
+       if (sl->xbuff == NULL)
                goto noxbuff;
-       }
 
        sl->buffsize = len;
        sl->rcount   = 0;
@@ -480,11 +478,12 @@ static int x25_asy_open(struct net_device *dev)
        sl->flags   &= (1 << SLF_INUSE);      /* Clear ESCAPE & ERROR flags */
 
        netif_start_queue(dev);
-                       
+
        /*
         *      Now attach LAPB
         */
-       if((err=lapb_register(dev, &x25_asy_callbacks))==LAPB_OK)
+       err = lapb_register(dev, &x25_asy_callbacks);
+       if (err == LAPB_OK)
                return 0;
 
        /* Cleanup */
@@ -499,18 +498,20 @@ norbuff:
 /* Close the low-level part of the X.25 channel. Easy! */
 static int x25_asy_close(struct net_device *dev)
 {
-       struct x25_asy *sl = (struct x25_asy*)(dev->priv);
+       struct x25_asy *sl = dev->priv;
        int err;
 
        spin_lock(&sl->lock);
-       if (sl->tty) 
+       if (sl->tty)
                sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 
        netif_stop_queue(dev);
        sl->rcount = 0;
        sl->xleft  = 0;
-       if((err=lapb_unregister(dev))!=LAPB_OK)
-               printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",err);
+       err = lapb_unregister(dev);
+       if (err != LAPB_OK)
+               printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",
+                       err);
        spin_unlock(&sl->lock);
        return 0;
 }
@@ -521,8 +522,9 @@ static int x25_asy_close(struct net_device *dev)
  * a block of X.25 data has been received, which can now be decapsulated
  * and sent on to some IP layer for further processing.
  */
-static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
+
+static void x25_asy_receive_buf(struct tty_struct *tty,
+                               const unsigned char *cp, char *fp, int count)
 {
        struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
 
@@ -533,9 +535,8 @@ static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp,
        /* Read the characters out of the buffer */
        while (count--) {
                if (fp && *fp++) {
-                       if (!test_and_set_bit(SLF_ERROR, &sl->flags))  {
+                       if (!test_and_set_bit(SLF_ERROR, &sl->flags))
                                sl->stats.rx_errors++;
-                       }
                        cp++;
                        continue;
                }
@@ -556,31 +557,31 @@ static int x25_asy_open_tty(struct tty_struct *tty)
        struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
        int err;
 
+       if (tty->ops->write == NULL)
+               return -EOPNOTSUPP;
+
        /* First make sure we're not already connected. */
-       if (sl && sl->magic == X25_ASY_MAGIC) {
+       if (sl && sl->magic == X25_ASY_MAGIC)
                return -EEXIST;
-       }
 
        /* OK.  Find a free X.25 channel to use. */
-       if ((sl = x25_asy_alloc()) == NULL) {
+       sl = x25_asy_alloc();
+       if (sl == NULL)
                return -ENFILE;
-       }
 
        sl->tty = tty;
        tty->disc_data = sl;
        tty->receive_room = 65536;
-       if (tty->driver->flush_buffer)  {
-               tty->driver->flush_buffer(tty);
-       }
+       tty_driver_flush_buffer(tty);
        tty_ldisc_flush(tty);
 
        /* Restore default settings */
        sl->dev->type = ARPHRD_X25;
-       
+
        /* Perform the low-level X.25 async init */
-       if ((err = x25_asy_open(sl->dev)))
+       err = x25_asy_open(sl->dev);
+       if (err)
                return err;
-
        /* Done.  We have linked the TTY line to a channel. */
        return sl->dev->base_addr;
 }
@@ -601,9 +602,7 @@ static void x25_asy_close_tty(struct tty_struct *tty)
                return;
 
        if (sl->dev->flags & IFF_UP)
-       {
-               (void) dev_close(sl->dev);
-       }
+               dev_close(sl->dev);
 
        tty->disc_data = NULL;
        sl->tty = NULL;
@@ -613,8 +612,7 @@ static void x25_asy_close_tty(struct tty_struct *tty)
 
 static struct net_device_stats *x25_asy_get_stats(struct net_device *dev)
 {
-       struct x25_asy *sl = (struct x25_asy*)(dev->priv);
-
+       struct x25_asy *sl = dev->priv;
        return &sl->stats;
 }
 
@@ -641,21 +639,19 @@ int x25_asy_esc(unsigned char *s, unsigned char *d, int len)
         * character sequence, according to the X.25 protocol.
         */
 
-       while (len-- > 0) 
-       {
-               switch(c = *s++) 
-               {
-                       case X25_END:
-                               *ptr++ = X25_ESC;
-                               *ptr++ = X25_ESCAPE(X25_END);
-                               break;
-                       case X25_ESC:
-                               *ptr++ = X25_ESC;
-                               *ptr++ = X25_ESCAPE(X25_ESC);
-                               break;
-                        default:
-                               *ptr++ = c;
-                               break;
+       while (len-- > 0) {
+               switch (c = *s++) {
+               case X25_END:
+                       *ptr++ = X25_ESC;
+                       *ptr++ = X25_ESCAPE(X25_END);
+                       break;
+               case X25_ESC:
+                       *ptr++ = X25_ESC;
+                       *ptr++ = X25_ESCAPE(X25_ESC);
+                       break;
+               default:
+                       *ptr++ = c;
+                       break;
                }
        }
        *ptr++ = X25_END;
@@ -665,31 +661,25 @@ int x25_asy_esc(unsigned char *s, unsigned char *d, int len)
 static void x25_asy_unesc(struct x25_asy *sl, unsigned char s)
 {
 
-       switch(s) 
-       {
-               case X25_END:
-                       if (!test_and_clear_bit(SLF_ERROR, &sl->flags) && (sl->rcount > 2))  
-                       {
-                               x25_asy_bump(sl);
-                       }
-                       clear_bit(SLF_ESCAPE, &sl->flags);
-                       sl->rcount = 0;
-                       return;
-
-               case X25_ESC:
-                       set_bit(SLF_ESCAPE, &sl->flags);
-                       return;
-                       
-               case X25_ESCAPE(X25_ESC):
-               case X25_ESCAPE(X25_END):
-                       if (test_and_clear_bit(SLF_ESCAPE, &sl->flags))
-                               s = X25_UNESCAPE(s);
-                       break;
-       }
-       if (!test_bit(SLF_ERROR, &sl->flags))  
-       {
-               if (sl->rcount < sl->buffsize)  
-               {
+       switch (s) {
+       case X25_END:
+               if (!test_and_clear_bit(SLF_ERROR, &sl->flags)
+                       && sl->rcount > 2)
+                       x25_asy_bump(sl);
+               clear_bit(SLF_ESCAPE, &sl->flags);
+               sl->rcount = 0;
+               return;
+       case X25_ESC:
+               set_bit(SLF_ESCAPE, &sl->flags);
+               return;
+       case X25_ESCAPE(X25_ESC):
+       case X25_ESCAPE(X25_END):
+               if (test_and_clear_bit(SLF_ESCAPE, &sl->flags))
+                       s = X25_UNESCAPE(s);
+               break;
+       }
+       if (!test_bit(SLF_ERROR, &sl->flags)) {
+               if (sl->rcount < sl->buffsize) {
                        sl->rbuff[sl->rcount++] = s;
                        return;
                }
@@ -709,7 +699,7 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file,
        if (!sl || sl->magic != X25_ASY_MAGIC)
                return -EINVAL;
 
-       switch(cmd) {
+       switch (cmd) {
        case SIOCGIFNAME:
                if (copy_to_user((void __user *)arg, sl->dev->name,
                                        strlen(sl->dev->name) + 1))
@@ -724,8 +714,8 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file,
 
 static int x25_asy_open_dev(struct net_device *dev)
 {
-       struct x25_asy *sl = (struct x25_asy*)(dev->priv);
-       if(sl->tty==NULL)
+       struct x25_asy *sl = dev->priv;
+       if (sl->tty == NULL)
                return -ENODEV;
        return 0;
 }
@@ -741,9 +731,9 @@ static void x25_asy_setup(struct net_device *dev)
        set_bit(SLF_INUSE, &sl->flags);
 
        /*
-        *      Finish setting up the DEVICE info. 
+        *      Finish setting up the DEVICE info.
         */
-        
+
        dev->mtu                = SL_MTU;
        dev->hard_start_xmit    = x25_asy_xmit;
        dev->tx_timeout         = x25_asy_timeout;
@@ -778,9 +768,10 @@ static int __init init_x25_asy(void)
                x25_asy_maxdev = 4; /* Sanity */
 
        printk(KERN_INFO "X.25 async: version 0.00 ALPHA "
-                       "(dynamic channels, max=%d).\n", x25_asy_maxdev );
+                       "(dynamic channels, max=%d).\n", x25_asy_maxdev);
 
-       x25_asy_devs = kcalloc(x25_asy_maxdev, sizeof(struct net_device*), GFP_KERNEL);
+       x25_asy_devs = kcalloc(x25_asy_maxdev, sizeof(struct net_device *),
+                               GFP_KERNEL);
        if (!x25_asy_devs) {
                printk(KERN_WARNING "X25 async: Can't allocate x25_asy_ctrls[] "
                                "array! Uaargh! (-> No X.25 available)\n");
@@ -802,7 +793,7 @@ static void __exit exit_x25_asy(void)
                        struct x25_asy *sl = dev->priv;
 
                        spin_lock_bh(&sl->lock);
-                       if (sl->tty) 
+                       if (sl->tty)
                                tty_hangup(sl->tty);
 
                        spin_unlock_bh(&sl->lock);
index 932d6b1c9d0bad70b45a285faafedd602426c5e1..45f47c1c0a353ec148a7ac60828954df9b042e90 100644 (file)
@@ -3657,7 +3657,7 @@ void mpi_receive_802_11 (struct airo_info *ai)
        ptr += hdrlen;
        if (hdrlen == 24)
                ptr += 6;
-       gap = le16_to_cpu(get_unaligned((__le16 *)ptr));
+       gap = get_unaligned_le16(ptr);
        ptr += sizeof(__le16);
        if (gap) {
                if (gap <= 8)
@@ -4347,24 +4347,28 @@ static int proc_config_open( struct inode *inode, struct file *file );
 static int proc_wepkey_open( struct inode *inode, struct file *file );
 
 static const struct file_operations proc_statsdelta_ops = {
+       .owner          = THIS_MODULE,
        .read           = proc_read,
        .open           = proc_statsdelta_open,
        .release        = proc_close
 };
 
 static const struct file_operations proc_stats_ops = {
+       .owner          = THIS_MODULE,
        .read           = proc_read,
        .open           = proc_stats_open,
        .release        = proc_close
 };
 
 static const struct file_operations proc_status_ops = {
+       .owner          = THIS_MODULE,
        .read           = proc_read,
        .open           = proc_status_open,
        .release        = proc_close
 };
 
 static const struct file_operations proc_SSID_ops = {
+       .owner          = THIS_MODULE,
        .read           = proc_read,
        .write          = proc_write,
        .open           = proc_SSID_open,
@@ -4372,6 +4376,7 @@ static const struct file_operations proc_SSID_ops = {
 };
 
 static const struct file_operations proc_BSSList_ops = {
+       .owner          = THIS_MODULE,
        .read           = proc_read,
        .write          = proc_write,
        .open           = proc_BSSList_open,
@@ -4379,6 +4384,7 @@ static const struct file_operations proc_BSSList_ops = {
 };
 
 static const struct file_operations proc_APList_ops = {
+       .owner          = THIS_MODULE,
        .read           = proc_read,
        .write          = proc_write,
        .open           = proc_APList_open,
@@ -4386,6 +4392,7 @@ static const struct file_operations proc_APList_ops = {
 };
 
 static const struct file_operations proc_config_ops = {
+       .owner          = THIS_MODULE,
        .read           = proc_read,
        .write          = proc_write,
        .open           = proc_config_open,
@@ -4393,6 +4400,7 @@ static const struct file_operations proc_config_ops = {
 };
 
 static const struct file_operations proc_wepkey_ops = {
+       .owner          = THIS_MODULE,
        .read           = proc_read,
        .write          = proc_write,
        .open           = proc_wepkey_open,
@@ -4411,10 +4419,6 @@ struct proc_data {
        void (*on_close) (struct inode *, struct file *);
 };
 
-#ifndef SETPROC_OPS
-#define SETPROC_OPS(entry, ops) (entry)->proc_fops = &(ops)
-#endif
-
 static int setup_proc_entry( struct net_device *dev,
                             struct airo_info *apriv ) {
        struct proc_dir_entry *entry;
@@ -4430,100 +4434,76 @@ static int setup_proc_entry( struct net_device *dev,
        apriv->proc_entry->owner = THIS_MODULE;
 
        /* Setup the StatsDelta */
-       entry = create_proc_entry("StatsDelta",
-                                 S_IFREG | (S_IRUGO&proc_perm),
-                                 apriv->proc_entry);
+       entry = proc_create_data("StatsDelta",
+                                S_IFREG | (S_IRUGO&proc_perm),
+                                apriv->proc_entry, &proc_statsdelta_ops, dev);
        if (!entry)
                goto fail_stats_delta;
        entry->uid = proc_uid;
        entry->gid = proc_gid;
-       entry->data = dev;
-       entry->owner = THIS_MODULE;
-       SETPROC_OPS(entry, proc_statsdelta_ops);
 
        /* Setup the Stats */
-       entry = create_proc_entry("Stats",
-                                 S_IFREG | (S_IRUGO&proc_perm),
-                                 apriv->proc_entry);
+       entry = proc_create_data("Stats",
+                                S_IFREG | (S_IRUGO&proc_perm),
+                                apriv->proc_entry, &proc_stats_ops, dev);
        if (!entry)
                goto fail_stats;
        entry->uid = proc_uid;
        entry->gid = proc_gid;
-       entry->data = dev;
-       entry->owner = THIS_MODULE;
-       SETPROC_OPS(entry, proc_stats_ops);
 
        /* Setup the Status */
-       entry = create_proc_entry("Status",
-                                 S_IFREG | (S_IRUGO&proc_perm),
-                                 apriv->proc_entry);
+       entry = proc_create_data("Status",
+                                S_IFREG | (S_IRUGO&proc_perm),
+                                apriv->proc_entry, &proc_status_ops, dev);
        if (!entry)
                goto fail_status;
        entry->uid = proc_uid;
        entry->gid = proc_gid;
-       entry->data = dev;
-       entry->owner = THIS_MODULE;
-       SETPROC_OPS(entry, proc_status_ops);
 
        /* Setup the Config */
-       entry = create_proc_entry("Config",
-                                 S_IFREG | proc_perm,
-                                 apriv->proc_entry);
+       entry = proc_create_data("Config",
+                                S_IFREG | proc_perm,
+                                apriv->proc_entry, &proc_config_ops, dev);
        if (!entry)
                goto fail_config;
        entry->uid = proc_uid;
        entry->gid = proc_gid;
-       entry->data = dev;
-       entry->owner = THIS_MODULE;
-       SETPROC_OPS(entry, proc_config_ops);
 
        /* Setup the SSID */
-       entry = create_proc_entry("SSID",
-                                 S_IFREG | proc_perm,
-                                 apriv->proc_entry);
+       entry = proc_create_data("SSID",
+                                S_IFREG | proc_perm,
+                                apriv->proc_entry, &proc_SSID_ops, dev);
        if (!entry)
                goto fail_ssid;
        entry->uid = proc_uid;
        entry->gid = proc_gid;
-       entry->data = dev;
-       entry->owner = THIS_MODULE;
-       SETPROC_OPS(entry, proc_SSID_ops);
 
        /* Setup the APList */
-       entry = create_proc_entry("APList",
-                                 S_IFREG | proc_perm,
-                                 apriv->proc_entry);
+       entry = proc_create_data("APList",
+                                S_IFREG | proc_perm,
+                                apriv->proc_entry, &proc_APList_ops, dev);
        if (!entry)
                goto fail_aplist;
        entry->uid = proc_uid;
        entry->gid = proc_gid;
-       entry->data = dev;
-       entry->owner = THIS_MODULE;
-       SETPROC_OPS(entry, proc_APList_ops);
 
        /* Setup the BSSList */
-       entry = create_proc_entry("BSSList",
-                                 S_IFREG | proc_perm,
-                                 apriv->proc_entry);
+       entry = proc_create_data("BSSList",
+                                S_IFREG | proc_perm,
+                                apriv->proc_entry, &proc_BSSList_ops, dev);
        if (!entry)
                goto fail_bsslist;
        entry->uid = proc_uid;
        entry->gid = proc_gid;
-       entry->data = dev;
-       entry->owner = THIS_MODULE;
-       SETPROC_OPS(entry, proc_BSSList_ops);
 
        /* Setup the WepKey */
-       entry = create_proc_entry("WepKey",
-                                 S_IFREG | proc_perm,
-                                 apriv->proc_entry);
+       entry = proc_create_data("WepKey",
+                                S_IFREG | proc_perm,
+                                apriv->proc_entry, &proc_wepkey_ops, dev);
        if (!entry)
                goto fail_wepkey;
        entry->uid = proc_uid;
        entry->gid = proc_gid;
-       entry->data = dev;
-       entry->owner = THIS_MODULE;
-       SETPROC_OPS(entry, proc_wepkey_ops);
 
        return 0;
 
@@ -5625,9 +5605,9 @@ static int __init airo_init_module( void )
        int have_isa_dev = 0;
 #endif
 
-       airo_entry = create_proc_entry("aironet",
+       airo_entry = create_proc_entry("driver/aironet",
                                       S_IFDIR | airo_perm,
-                                      proc_root_driver);
+                                      NULL);
 
        if (airo_entry) {
                airo_entry->uid = proc_uid;
@@ -5651,7 +5631,7 @@ static int __init airo_init_module( void )
        airo_print_info("", "Finished probing for PCI adapters");
 
        if (i) {
-               remove_proc_entry("aironet", proc_root_driver);
+               remove_proc_entry("driver/aironet", NULL);
                return i;
        }
 #endif
@@ -5673,7 +5653,7 @@ static void __exit airo_cleanup_module( void )
 #ifdef CONFIG_PCI
        pci_unregister_driver(&airo_driver);
 #endif
-       remove_proc_entry("aironet", proc_root_driver);
+       remove_proc_entry("driver/aironet", NULL);
 }
 
 /*
index e18305b781c91163deef0912c8a1927897f960ce..4e5c8fc35200a8b0abcaaefe4e8148cf85cb20b5 100644 (file)
 #include "reg.h"
 #include "debug.h"
 
-/* unaligned little endian access */
-#define LE_READ_2(_p) (le16_to_cpu(get_unaligned((__le16 *)(_p))))
-#define LE_READ_4(_p) (le32_to_cpu(get_unaligned((__le32 *)(_p))))
-
 enum {
        ATH_LED_TX,
        ATH_LED_RX,
@@ -2909,9 +2905,9 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
                        if (!mclist)
                                break;
                        /* calculate XOR of eight 6-bit values */
-                       val = LE_READ_4(mclist->dmi_addr + 0);
+                       val = get_unaligned_le32(mclist->dmi_addr + 0);
                        pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
-                       val = LE_READ_4(mclist->dmi_addr + 3);
+                       val = get_unaligned_le32(mclist->dmi_addr + 3);
                        pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
                        pos &= 0x3f;
                        mfilt[pos / 32] |= (1 << (pos % 32));
index 4bf8a99099fee7713f357b5f3f450148441c19a6..8c24cd72aaca711ae9852fcdd0b0e0c2bb44b325 100644 (file)
@@ -2171,7 +2171,7 @@ static int b43_write_initvals(struct b43_wldev *dev,
                                goto err_format;
                        array_size -= sizeof(iv->data.d32);
 
-                       value = be32_to_cpu(get_unaligned(&iv->data.d32));
+                       value = get_unaligned_be32(&iv->data.d32);
                        b43_write32(dev, offset, value);
 
                        iv = (const struct b43_iv *)((const uint8_t *)iv +
index ef829ee8ffd47f3bd538c74964de21425d056a3f..14a5eea2573e8a01e28f2b9cb23cda7f4450bc8e 100644 (file)
@@ -1720,7 +1720,7 @@ static int b43legacy_write_initvals(struct b43legacy_wldev *dev,
                                goto err_format;
                        array_size -= sizeof(iv->data.d32);
 
-                       value = be32_to_cpu(get_unaligned(&iv->data.d32));
+                       value = get_unaligned_be32(&iv->data.d32);
                        b43legacy_write32(dev, offset, value);
 
                        iv = (const struct b43legacy_iv *)((const uint8_t *)iv +
index 598e4eef4f4080181a3cd089a617ba62ed453356..d3406830c8e3591231d7234680effc342d4ef69a 100644 (file)
@@ -554,40 +554,36 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv,
        iwl3945_rt->rt_hdr.it_pad = 0;
 
        /* total header + data */
-       put_unaligned(cpu_to_le16(sizeof(*iwl3945_rt)),
-                     &iwl3945_rt->rt_hdr.it_len);
+       put_unaligned_le16(sizeof(*iwl3945_rt), &iwl3945_rt->rt_hdr.it_len);
 
        /* Indicate all the fields we add to the radiotap header */
-       put_unaligned(cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
-                                 (1 << IEEE80211_RADIOTAP_FLAGS) |
-                                 (1 << IEEE80211_RADIOTAP_RATE) |
-                                 (1 << IEEE80211_RADIOTAP_CHANNEL) |
-                                 (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
-                                 (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
-                                 (1 << IEEE80211_RADIOTAP_ANTENNA)),
-                     &iwl3945_rt->rt_hdr.it_present);
+       put_unaligned_le32((1 << IEEE80211_RADIOTAP_TSFT) |
+                          (1 << IEEE80211_RADIOTAP_FLAGS) |
+                          (1 << IEEE80211_RADIOTAP_RATE) |
+                          (1 << IEEE80211_RADIOTAP_CHANNEL) |
+                          (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
+                          (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
+                          (1 << IEEE80211_RADIOTAP_ANTENNA),
+                       &iwl3945_rt->rt_hdr.it_present);
 
        /* Zero the flags, we'll add to them as we go */
        iwl3945_rt->rt_flags = 0;
 
-       put_unaligned(cpu_to_le64(tsf), &iwl3945_rt->rt_tsf);
+       put_unaligned_le64(tsf, &iwl3945_rt->rt_tsf);
 
        iwl3945_rt->rt_dbmsignal = signal;
        iwl3945_rt->rt_dbmnoise = noise;
 
        /* Convert the channel frequency and set the flags */
-       put_unaligned(cpu_to_le16(stats->freq), &iwl3945_rt->rt_channelMHz);
+       put_unaligned_le16(stats->freq, &iwl3945_rt->rt_channelMHz);
        if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK))
-               put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM |
-                                         IEEE80211_CHAN_5GHZ),
+               put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ,
                              &iwl3945_rt->rt_chbitmask);
        else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK)
-               put_unaligned(cpu_to_le16(IEEE80211_CHAN_CCK |
-                                         IEEE80211_CHAN_2GHZ),
+               put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ,
                              &iwl3945_rt->rt_chbitmask);
        else    /* 802.11g */
-               put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM |
-                                         IEEE80211_CHAN_2GHZ),
+               put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ,
                              &iwl3945_rt->rt_chbitmask);
 
        if (rate == -1)
index e72c97a0d6c1f36bbed6edbf2d50f38e8f57a1a0..1a409fcc80d3fdb30f65a703a2938bcba58af8d2 100644 (file)
@@ -522,7 +522,7 @@ static int lbs_process_bss(struct bss_descriptor *bss,
 
        if (*bytesleft >= sizeof(beaconsize)) {
                /* Extract & convert beacon size from the command buffer */
-               beaconsize = le16_to_cpu(get_unaligned((__le16 *)*pbeaconinfo));
+               beaconsize = get_unaligned_le16(*pbeaconinfo);
                *bytesleft -= sizeof(beaconsize);
                *pbeaconinfo += sizeof(beaconsize);
        }
index bced3fe1cf8a412968ebc46375b297349b5fcc8d..5dd23c93497db90163365b84a7e62917571cd122 100644 (file)
@@ -767,42 +767,18 @@ static __u8 *UnStuffData(__u8 * src, __u8 * end, __u8 * dst,
 /************************************************************************/
 /* General routines for STRIP                                          */
 
-/*
- * get_baud returns the current baud rate, as one of the constants defined in
- * termbits.h
- * If the user has issued a baud rate override using the 'setserial' command
- * and the logical current rate is set to 38.4, then the true baud rate
- * currently in effect (57.6 or 115.2) is returned.
- */
-static unsigned int get_baud(struct tty_struct *tty)
-{
-       if (!tty || !tty->termios)
-               return (0);
-       if ((tty->termios->c_cflag & CBAUD) == B38400 && tty->driver_data) {
-               struct async_struct *info =
-                   (struct async_struct *) tty->driver_data;
-               if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-                       return (B57600);
-               if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-                       return (B115200);
-       }
-       return (tty->termios->c_cflag & CBAUD);
-}
-
 /*
  * set_baud sets the baud rate to the rate defined by baudcode
- * Note: The rate B38400 should be avoided, because the user may have
- * issued a 'setserial' speed override to map that to a different speed.
- * We could achieve a true rate of 38400 if we needed to by cancelling
- * any user speed override that is in place, but that might annoy the
- * user, so it is simplest to just avoid using 38400.
  */
-static void set_baud(struct tty_struct *tty, unsigned int baudcode)
+static void set_baud(struct tty_struct *tty, speed_t baudrate)
 {
-       struct ktermios old_termios = *(tty->termios);
-       tty->termios->c_cflag &= ~CBAUD;        /* Clear the old baud setting */
-       tty->termios->c_cflag |= baudcode;      /* Set the new baud setting */
-       tty->driver->set_termios(tty, &old_termios);
+       struct ktermios old_termios;
+
+       mutex_lock(&tty->termios_mutex);
+       old_termios =*(tty->termios);
+       tty_encode_baud_rate(tty, baudrate, baudrate);
+       tty->ops->set_termios(tty, &old_termios);
+       mutex_unlock(&tty->termios_mutex);
 }
 
 /*
@@ -1217,7 +1193,7 @@ static void ResetRadio(struct strip *strip_info)
        strip_info->watchdog_doreset = jiffies + 1 * HZ;
 
        /* If the user has selected a baud rate above 38.4 see what magic we have to do */
-       if (strip_info->user_baud > B38400) {
+       if (strip_info->user_baud > 38400) {
                /*
                 * Subtle stuff: Pay attention :-)
                 * If the serial port is currently at the user's selected (>38.4) rate,
@@ -1227,17 +1203,17 @@ static void ResetRadio(struct strip *strip_info)
                 * issued the ATS304 command last time through, so this time we restore
                 * the user's selected rate and issue the normal starmode reset string.
                 */
-               if (strip_info->user_baud == get_baud(tty)) {
+               if (strip_info->user_baud == tty_get_baud_rate(tty)) {
                        static const char b0[] = "ate0q1s304=57600\r";
                        static const char b1[] = "ate0q1s304=115200\r";
                        static const StringDescriptor baudstring[2] =
                            { {b0, sizeof(b0) - 1}
                        , {b1, sizeof(b1) - 1}
                        };
-                       set_baud(tty, B19200);
-                       if (strip_info->user_baud == B57600)
+                       set_baud(tty, 19200);
+                       if (strip_info->user_baud == 57600)
                                s = baudstring[0];
-                       else if (strip_info->user_baud == B115200)
+                       else if (strip_info->user_baud == 115200)
                                s = baudstring[1];
                        else
                                s = baudstring[1];      /* For now */
@@ -1245,7 +1221,7 @@ static void ResetRadio(struct strip *strip_info)
                        set_baud(tty, strip_info->user_baud);
        }
 
-       tty->driver->write(tty, s.string, s.length);
+       tty->ops->write(tty, s.string, s.length);
 #ifdef EXT_COUNTERS
        strip_info->tx_ebytes += s.length;
 #endif
@@ -1267,7 +1243,7 @@ static void strip_write_some_more(struct tty_struct *tty)
 
        if (strip_info->tx_left > 0) {
                int num_written =
-                   tty->driver->write(tty, strip_info->tx_head,
+                   tty->ops->write(tty, strip_info->tx_head,
                                      strip_info->tx_left);
                strip_info->tx_left -= num_written;
                strip_info->tx_head += num_written;
@@ -2457,7 +2433,7 @@ static int strip_open_low(struct net_device *dev)
        strip_info->working = FALSE;
        strip_info->firmware_level = NoStructure;
        strip_info->next_command = CompatibilityCommand;
-       strip_info->user_baud = get_baud(strip_info->tty);
+       strip_info->user_baud = tty_get_baud_rate(strip_info->tty);
 
        printk(KERN_INFO "%s: Initializing Radio.\n",
               strip_info->dev->name);
@@ -2631,6 +2607,13 @@ static int strip_open(struct tty_struct *tty)
        if (strip_info && strip_info->magic == STRIP_MAGIC)
                return -EEXIST;
 
+       /*
+        * We need a write method.
+        */
+
+       if (tty->ops->write == NULL)
+               return -EOPNOTSUPP;
+
        /*
         * OK.  Find a free STRIP channel to use.
         */
@@ -2652,8 +2635,7 @@ static int strip_open(struct tty_struct *tty)
        tty->disc_data = strip_info;
        tty->receive_room = 65536;
 
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       tty_driver_flush_buffer(tty);
 
        /*
         * Restore default settings
index e34675c2f8fc9cb1c5e6394f450c4fde7120b2d9..5316074f39f0b0c28e73ace87813ecb0e3883ef6 100644 (file)
@@ -545,11 +545,11 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
         * be padded. Unaligned access might also happen if the length_info
         * structure is not present.
         */
-       if (get_unaligned(&length_info->tag) == cpu_to_le16(RX_LENGTH_INFO_TAG))
+       if (get_unaligned_le16(&length_info->tag) == RX_LENGTH_INFO_TAG)
        {
                unsigned int l, k, n;
                for (i = 0, l = 0;; i++) {
-                       k = le16_to_cpu(get_unaligned(&length_info->length[i]));
+                       k = get_unaligned_le16(&length_info->length[i]);
                        if (k == 0)
                                return;
                        n = l+k;
index 24640726f8bbde0b0d7ee0d1517abade187dfe7a..57e1f495b9fc0456db009a9540ec0f7111295b51 100644 (file)
@@ -1062,7 +1062,7 @@ static int yellowfin_rx(struct net_device *dev)
                buf_addr = rx_skb->data;
                data_size = (le32_to_cpu(desc->dbdma_cmd) -
                        le32_to_cpu(desc->result_status)) & 0xffff;
-               frame_status = le16_to_cpu(get_unaligned((__le16*)&(buf_addr[data_size - 2])));
+               frame_status = get_unaligned_le16(&(buf_addr[data_size - 2]));
                if (yellowfin_debug > 4)
                        printk(KERN_DEBUG "  yellowfin_rx() status was %4.4x.\n",
                                   frame_status);
index e07492be1f4ac36a418896f77f45a4a25fffdaa7..208dd12825bc4314be4bbba70a9c898d8b99ae92 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/nubus.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/init.h>
 #include <linux/module.h>
 
 #include <asm/byteorder.h>
 
 static int
-get_nubus_dev_info(char *buf, char **start, off_t pos, int count)
+nubus_devices_proc_show(struct seq_file *m, void *v)
 {
        struct nubus_dev *dev = nubus_devices;
-       off_t at = 0;
-       int len, cnt;
 
-       cnt = 0;
-       while (dev && count > cnt) {
-               len = sprintf(buf, "%x\t%04x %04x %04x %04x",
+       while (dev) {
+               seq_printf(m, "%x\t%04x %04x %04x %04x",
                              dev->board->slot,
                              dev->category,
                              dev->type,
                              dev->dr_sw,
                              dev->dr_hw);
-               len += sprintf(buf+len,
-                              "\t%08lx",
-                              dev->board->slot_addr);
-               buf[len++] = '\n';
-               at += len;
-               if (at >= pos) {
-                       if (!*start) {
-                               *start = buf + (pos - (at - len));
-                               cnt = at - pos;
-                       } else
-                               cnt += len;
-                       buf += len;
-               }
+               seq_printf(m, "\t%08lx\n", dev->board->slot_addr);
                dev = dev->next;
        }
-       return (count > cnt) ? cnt : count;
+       return 0;
+}
+
+static int nubus_devices_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, nubus_devices_proc_show, NULL);
 }
 
+static const struct file_operations nubus_devices_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = nubus_devices_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
 static struct proc_dir_entry *proc_bus_nubus_dir;
 
 static void nubus_proc_subdir(struct nubus_dev* dev,
@@ -171,8 +170,7 @@ void __init nubus_proc_init(void)
 {
        if (!MACH_IS_MAC)
                return;
-       proc_bus_nubus_dir = proc_mkdir("nubus", proc_bus);
-       create_proc_info_entry("devices", 0, proc_bus_nubus_dir,
-                               get_nubus_dev_info);
+       proc_bus_nubus_dir = proc_mkdir("bus/nubus", NULL);
+       proc_create("devices", 0, proc_bus_nubus_dir, &nubus_devices_proc_fops);
        proc_bus_nubus_add_devices();
 }
index 62db3c3fe4dcbd35dcd6181c4061954e4b0b0d87..07d2a8d4498f395f52e822b9ff493555e1f3d600 100644 (file)
@@ -1551,8 +1551,7 @@ static int __init ccio_probe(struct parisc_device *dev)
 {
        int i;
        struct ioc *ioc, **ioc_p = &ioc_list;
-       struct proc_dir_entry *info_entry, *bitmap_entry;
-       
+
        ioc = kzalloc(sizeof(struct ioc), GFP_KERNEL);
        if (ioc == NULL) {
                printk(KERN_ERR MODULE_NAME ": memory allocation failure\n");
@@ -1580,13 +1579,10 @@ static int __init ccio_probe(struct parisc_device *dev)
        HBA_DATA(dev->dev.platform_data)->iommu = ioc;
        
        if (ioc_count == 0) {
-               info_entry = create_proc_entry(MODULE_NAME, 0, proc_runway_root);
-               if (info_entry)
-                       info_entry->proc_fops = &ccio_proc_info_fops;
-
-               bitmap_entry = create_proc_entry(MODULE_NAME"-bitmap", 0, proc_runway_root);
-               if (bitmap_entry)
-                       bitmap_entry->proc_fops = &ccio_proc_bitmap_fops;
+               proc_create(MODULE_NAME, 0, proc_runway_root,
+                           &ccio_proc_info_fops);
+               proc_create(MODULE_NAME"-bitmap", 0, proc_runway_root,
+                           &ccio_proc_bitmap_fops);
        }
 
        ioc_count++;
index 8c4d2c13d5f246057a42d73ac518637973fca79e..afc849bd3f58a9ebaf9a0a00785c7a1f068e935d 100644 (file)
@@ -1895,7 +1895,9 @@ sba_driver_callback(struct parisc_device *dev)
        int i;
        char *version;
        void __iomem *sba_addr = ioremap_nocache(dev->hpa.start, SBA_FUNC_SIZE);
-       struct proc_dir_entry *info_entry, *bitmap_entry, *root;
+#ifdef CONFIG_PROC_FS
+       struct proc_dir_entry *root;
+#endif
 
        sba_dump_ranges(sba_addr);
 
@@ -1973,14 +1975,8 @@ sba_driver_callback(struct parisc_device *dev)
                break;
        }
 
-       info_entry = create_proc_entry("sba_iommu", 0, root);
-       bitmap_entry = create_proc_entry("sba_iommu-bitmap", 0, root);
-
-       if (info_entry)
-               info_entry->proc_fops = &sba_proc_fops;
-
-       if (bitmap_entry)
-               bitmap_entry->proc_fops = &sba_proc_bitmap_fops;
+       proc_create("sba_iommu", 0, root, &sba_proc_fops);
+       proc_create("sba_iommu-bitmap", 0, root, &sba_proc_bitmap_fops);
 #endif
 
        parisc_vmerge_boundary = IOVP_SIZE;
index 54a6ef72906ed741e2a0ba4ddbeb343de5418480..0338b09126742300efd226e4fce332a0e2c0bbad 100644 (file)
@@ -76,7 +76,7 @@ int parport_wait_event (struct parport *port, signed long timeout)
                   semaphore. */
                return 1;
 
-       init_timer (&timer);
+       init_timer_on_stack(&timer);
        timer.expires = jiffies + timeout;
        timer.function = timeout_waiting_on_port;
        port_from_cookie[port->number % PARPORT_MAX] = port;
@@ -88,6 +88,8 @@ int parport_wait_event (struct parport *port, signed long timeout)
                /* Timed out. */
                ret = 1;
 
+       destroy_timer_on_stack(&timer);
+
        return ret;
 }
 
index 0e77ae2b71a0ed408fd4399ff154940005efcd4d..e6a7e847ee805cbdd24384c08bc532560097c398 100644 (file)
@@ -365,11 +365,11 @@ static int __devinit parport_init_chip(struct parisc_device *dev)
        if (boot_cpu_data.cpu_type > pcxt && !pdc_add_valid(port+4)) {
 
                /* Initialize bidirectional-mode (0x10) & data-tranfer-mode #1 (0x20) */
-               printk("%s: initialize bidirectional-mode.\n", __FUNCTION__);
+               printk("%s: initialize bidirectional-mode.\n", __func__);
                parport_writeb ( (0x10 + 0x20), port + 4);
 
        } else {
-               printk("%s: enhanced parport-modes not supported.\n", __FUNCTION__);
+               printk("%s: enhanced parport-modes not supported.\n", __func__);
        }
        
        p = parport_gsc_probe_port(port, 0, dev->irq,
index a8580893820513adfd07bd72e1c6d3404d886777..e0c2a4584ec61f22cf3be8d2cae19d6259dd0ef5 100644 (file)
@@ -1415,7 +1415,7 @@ static void __devinit winbond_check(int io, int key)
 {
        int devid,devrev,oldid,x_devid,x_devrev,x_oldid;
 
-       if (!request_region(io, 3, __FUNCTION__))
+       if (!request_region(io, 3, __func__))
                return;
 
        /* First probe without key */
@@ -1449,7 +1449,7 @@ static void __devinit winbond_check2(int io,int key)
 {
         int devid,devrev,oldid,x_devid,x_devrev,x_oldid;
 
-       if (!request_region(io, 3, __FUNCTION__))
+       if (!request_region(io, 3, __func__))
                return;
 
        /* First probe without the key */
@@ -1482,7 +1482,7 @@ static void __devinit smsc_check(int io, int key)
 {
         int id,rev,oldid,oldrev,x_id,x_rev,x_oldid,x_oldrev;
 
-       if (!request_region(io, 3, __FUNCTION__))
+       if (!request_region(io, 3, __func__))
                return;
 
        /* First probe without the key */
@@ -1547,7 +1547,7 @@ static void __devinit detect_and_report_it87(void)
        u8 r;
        if (verbose_probing)
                printk(KERN_DEBUG "IT8705 Super-IO detection, now testing port 2E ...\n");
-       if (!request_region(0x2e, 1, __FUNCTION__))
+       if (!request_region(0x2e, 1, __func__))
                return;
        outb(0x87, 0x2e);
        outb(0x01, 0x2e);
@@ -3082,6 +3082,7 @@ static struct pci_driver parport_pc_pci_driver;
 static int __init parport_pc_init_superio(int autoirq, int autodma) {return 0;}
 #endif /* CONFIG_PCI */
 
+#ifdef CONFIG_PNP
 
 static const struct pnp_device_id parport_pc_pnp_tbl[] = {
        /* Standard LPT Printer Port */
@@ -3148,6 +3149,9 @@ static struct pnp_driver parport_pc_pnp_driver = {
        .remove         = parport_pc_pnp_remove,
 };
 
+#else
+static struct pnp_driver parport_pc_pnp_driver;
+#endif /* CONFIG_PNP */
 
 static int __devinit parport_pc_platform_probe(struct platform_device *pdev)
 {
index f14267e197dd7677ca3d70bc9293f970fa35a3fe..8264a76804354ffb011a8abc8ce6dddc19cdd975 100644 (file)
@@ -93,11 +93,10 @@ struct controller {
        u8 slot_device_offset;
        u32 first_slot;         /* First physical slot number */  /* PCIE only has 1 slot */
        u8 slot_bus;            /* Bus where the slots handled by this controller sit */
-       u8 ctrlcap;
+       u32 slot_cap;
        u8 cap_base;
        struct timer_list poll_timer;
        volatile int cmd_busy;
-       spinlock_t lock;
 };
 
 #define INT_BUTTON_IGNORE              0
@@ -137,13 +136,13 @@ struct controller {
 #define HP_SUPR_RM_SUP 0x00000020
 #define EMI_PRSN       0x00020000
 
-#define ATTN_BUTTN(cap)                (cap & ATTN_BUTTN_PRSN)
-#define POWER_CTRL(cap)                (cap & PWR_CTRL_PRSN)
-#define MRL_SENS(cap)          (cap & MRL_SENS_PRSN)
-#define ATTN_LED(cap)          (cap & ATTN_LED_PRSN)
-#define PWR_LED(cap)           (cap & PWR_LED_PRSN) 
-#define HP_SUPR_RM(cap)                (cap & HP_SUPR_RM_SUP)
-#define EMI(cap)               (cap & EMI_PRSN)
+#define ATTN_BUTTN(ctrl)       ((ctrl)->slot_cap & ATTN_BUTTN_PRSN)
+#define POWER_CTRL(ctrl)       ((ctrl)->slot_cap & PWR_CTRL_PRSN)
+#define MRL_SENS(ctrl)         ((ctrl)->slot_cap & MRL_SENS_PRSN)
+#define ATTN_LED(ctrl)         ((ctrl)->slot_cap & ATTN_LED_PRSN)
+#define PWR_LED(ctrl)          ((ctrl)->slot_cap & PWR_LED_PRSN)
+#define HP_SUPR_RM(ctrl)       ((ctrl)->slot_cap & HP_SUPR_RM_SUP)
+#define EMI(ctrl)              ((ctrl)->slot_cap & EMI_PRSN)
 
 extern int pciehp_sysfs_enable_slot(struct slot *slot);
 extern int pciehp_sysfs_disable_slot(struct slot *slot);
index aee19f013d84bd379e0b19bdbbc3c0855c808e66..43d8ddb2d6796a3fa29ffa675506fe7ca4975ed9 100644 (file)
@@ -41,6 +41,7 @@ int pciehp_debug;
 int pciehp_poll_mode;
 int pciehp_poll_time;
 int pciehp_force;
+int pciehp_slot_with_bus;
 struct workqueue_struct *pciehp_wq;
 
 #define DRIVER_VERSION "0.4"
@@ -55,10 +56,12 @@ module_param(pciehp_debug, bool, 0644);
 module_param(pciehp_poll_mode, bool, 0644);
 module_param(pciehp_poll_time, int, 0644);
 module_param(pciehp_force, bool, 0644);
+module_param(pciehp_slot_with_bus, bool, 0644);
 MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not");
 MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not");
 MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds");
 MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing");
+MODULE_PARM_DESC(pciehp_slot_with_bus, "Use bus number in the slot name");
 
 #define PCIE_MODULE_NAME "pciehp"
 
@@ -193,8 +196,12 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
 
 static void make_slot_name(struct slot *slot)
 {
-       snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
-                slot->bus, slot->number);
+       if (pciehp_slot_with_bus)
+               snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
+                        slot->bus, slot->number);
+       else
+               snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d",
+                        slot->number);
 }
 
 static int init_slots(struct controller *ctrl)
@@ -251,7 +258,7 @@ static int init_slots(struct controller *ctrl)
                        goto error_info;
                }
                /* create additional sysfs entries */
-               if (EMI(ctrl->ctrlcap)) {
+               if (EMI(ctrl)) {
                        retval = sysfs_create_file(&hotplug_slot->kobj,
                                &hotplug_slot_attr_lock.attr);
                        if (retval) {
@@ -284,7 +291,7 @@ static void cleanup_slots(struct controller *ctrl)
        list_for_each_safe(tmp, next, &ctrl->slot_list) {
                slot = list_entry(tmp, struct slot, slot_list);
                list_del(&slot->slot_list);
-               if (EMI(ctrl->ctrlcap))
+               if (EMI(ctrl))
                        sysfs_remove_file(&slot->hotplug_slot->kobj,
                                &hotplug_slot_attr_lock.attr);
                cancel_delayed_work(&slot->work);
@@ -305,7 +312,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
 
        hotplug_slot->info->attention_status = status;
 
-       if (ATTN_LED(slot->ctrl->ctrlcap))
+       if (ATTN_LED(slot->ctrl))
                slot->hpc_ops->set_attention_status(slot, status);
 
        return 0;
@@ -472,7 +479,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
                if (rc) /* -ENODEV: shouldn't happen, but deal with it */
                        value = 0;
        }
-       if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
+       if ((POWER_CTRL(ctrl)) && !value) {
                rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
                if (rc)
                        goto err_out_free_ctrl_slot;
index 0c481f7d2ab32b34db251344c43db67bc4d898a2..0a7aa628e95511910408a3bcb3a81ae023a16782 100644 (file)
@@ -178,7 +178,7 @@ u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
 static void set_slot_off(struct controller *ctrl, struct slot * pslot)
 {
        /* turn off slot, turn on Amber LED, turn off Green LED if supported*/
-       if (POWER_CTRL(ctrl->ctrlcap)) {
+       if (POWER_CTRL(ctrl)) {
                if (pslot->hpc_ops->power_off_slot(pslot)) {
                        err("%s: Issue of Slot Power Off command failed\n",
                            __func__);
@@ -186,10 +186,10 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
                }
        }
 
-       if (PWR_LED(ctrl->ctrlcap))
+       if (PWR_LED(ctrl))
                pslot->hpc_ops->green_led_off(pslot);
 
-       if (ATTN_LED(ctrl->ctrlcap)) {
+       if (ATTN_LED(ctrl)) {
                if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
                        err("%s: Issue of Set Attention Led command failed\n",
                            __func__);
@@ -214,14 +214,14 @@ static int board_added(struct slot *p_slot)
                        __func__, p_slot->device,
                        ctrl->slot_device_offset, p_slot->hp_slot);
 
-       if (POWER_CTRL(ctrl->ctrlcap)) {
+       if (POWER_CTRL(ctrl)) {
                /* Power on slot */
                retval = p_slot->hpc_ops->power_on_slot(p_slot);
                if (retval)
                        return retval;
        }
 
-       if (PWR_LED(ctrl->ctrlcap))
+       if (PWR_LED(ctrl))
                p_slot->hpc_ops->green_led_blink(p_slot);
 
        /* Wait for ~1 second */
@@ -254,7 +254,7 @@ static int board_added(struct slot *p_slot)
         */
        if (pcie_mch_quirk)
                pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
-       if (PWR_LED(ctrl->ctrlcap))
+       if (PWR_LED(ctrl))
                p_slot->hpc_ops->green_led_on(p_slot);
 
        return 0;
@@ -279,7 +279,7 @@ static int remove_board(struct slot *p_slot)
 
        dbg("In %s, hp_slot = %d\n", __func__, p_slot->hp_slot);
 
-       if (POWER_CTRL(ctrl->ctrlcap)) {
+       if (POWER_CTRL(ctrl)) {
                /* power off slot */
                retval = p_slot->hpc_ops->power_off_slot(p_slot);
                if (retval) {
@@ -289,7 +289,7 @@ static int remove_board(struct slot *p_slot)
                }
        }
 
-       if (PWR_LED(ctrl->ctrlcap))
+       if (PWR_LED(ctrl))
                /* turn off Green LED */
                p_slot->hpc_ops->green_led_off(p_slot);
 
@@ -327,7 +327,7 @@ static void pciehp_power_thread(struct work_struct *work)
        case POWERON_STATE:
                mutex_unlock(&p_slot->lock);
                if (pciehp_enable_slot(p_slot) &&
-                   PWR_LED(p_slot->ctrl->ctrlcap))
+                   PWR_LED(p_slot->ctrl))
                        p_slot->hpc_ops->green_led_off(p_slot);
                mutex_lock(&p_slot->lock);
                p_slot->state = STATIC_STATE;
@@ -409,9 +409,9 @@ static void handle_button_press_event(struct slot *p_slot)
                             "press.\n", p_slot->name);
                }
                /* blink green LED and turn off amber */
-               if (PWR_LED(ctrl->ctrlcap))
+               if (PWR_LED(ctrl))
                        p_slot->hpc_ops->green_led_blink(p_slot);
-               if (ATTN_LED(ctrl->ctrlcap))
+               if (ATTN_LED(ctrl))
                        p_slot->hpc_ops->set_attention_status(p_slot, 0);
 
                schedule_delayed_work(&p_slot->work, 5*HZ);
@@ -427,13 +427,13 @@ static void handle_button_press_event(struct slot *p_slot)
                dbg("%s: button cancel\n", __func__);
                cancel_delayed_work(&p_slot->work);
                if (p_slot->state == BLINKINGOFF_STATE) {
-                       if (PWR_LED(ctrl->ctrlcap))
+                       if (PWR_LED(ctrl))
                                p_slot->hpc_ops->green_led_on(p_slot);
                } else {
-                       if (PWR_LED(ctrl->ctrlcap))
+                       if (PWR_LED(ctrl))
                                p_slot->hpc_ops->green_led_off(p_slot);
                }
-               if (ATTN_LED(ctrl->ctrlcap))
+               if (ATTN_LED(ctrl))
                        p_slot->hpc_ops->set_attention_status(p_slot, 0);
                info("PCI slot #%s - action canceled due to button press\n",
                     p_slot->name);
@@ -492,16 +492,16 @@ static void interrupt_event_handler(struct work_struct *work)
                handle_button_press_event(p_slot);
                break;
        case INT_POWER_FAULT:
-               if (!POWER_CTRL(ctrl->ctrlcap))
+               if (!POWER_CTRL(ctrl))
                        break;
-               if (ATTN_LED(ctrl->ctrlcap))
+               if (ATTN_LED(ctrl))
                        p_slot->hpc_ops->set_attention_status(p_slot, 1);
-               if (PWR_LED(ctrl->ctrlcap))
+               if (PWR_LED(ctrl))
                        p_slot->hpc_ops->green_led_off(p_slot);
                break;
        case INT_PRESENCE_ON:
        case INT_PRESENCE_OFF:
-               if (!HP_SUPR_RM(ctrl->ctrlcap))
+               if (!HP_SUPR_RM(ctrl))
                        break;
                dbg("Surprise Removal\n");
                update_slot_info(p_slot);
@@ -531,7 +531,7 @@ int pciehp_enable_slot(struct slot *p_slot)
                mutex_unlock(&p_slot->ctrl->crit_sect);
                return -ENODEV;
        }
-       if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
+       if (MRL_SENS(p_slot->ctrl)) {
                rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
                if (rc || getstatus) {
                        info("%s: latch open on slot(%s)\n", __func__,
@@ -541,7 +541,7 @@ int pciehp_enable_slot(struct slot *p_slot)
                }
        }
 
-       if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
+       if (POWER_CTRL(p_slot->ctrl)) {
                rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
                if (rc || getstatus) {
                        info("%s: already enabled on slot(%s)\n", __func__,
@@ -576,7 +576,7 @@ int pciehp_disable_slot(struct slot *p_slot)
        /* Check to see if (latch closed, card present, power on) */
        mutex_lock(&p_slot->ctrl->crit_sect);
 
-       if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) {
+       if (!HP_SUPR_RM(p_slot->ctrl)) {
                ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
                if (ret || !getstatus) {
                        info("%s: no adapter on slot(%s)\n", __func__,
@@ -586,7 +586,7 @@ int pciehp_disable_slot(struct slot *p_slot)
                }
        }
 
-       if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
+       if (MRL_SENS(p_slot->ctrl)) {
                ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
                if (ret || getstatus) {
                        info("%s: latch open on slot(%s)\n", __func__,
@@ -596,7 +596,7 @@ int pciehp_disable_slot(struct slot *p_slot)
                }
        }
 
-       if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
+       if (POWER_CTRL(p_slot->ctrl)) {
                ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
                if (ret || !getstatus) {
                        info("%s: already disabled slot(%s)\n", __func__,
index b4bbd07d1e3902ff756a2280c01480c2ffb73320..891f81a0400c92cb434dcdbbee95dbfa96c0e213 100644 (file)
@@ -221,6 +221,32 @@ static void start_int_poll_timer(struct controller *ctrl, int sec)
        add_timer(&ctrl->poll_timer);
 }
 
+static inline int pciehp_request_irq(struct controller *ctrl)
+{
+       int retval, irq = ctrl->pci_dev->irq;
+
+       /* Install interrupt polling timer. Start with 10 sec delay */
+       if (pciehp_poll_mode) {
+               init_timer(&ctrl->poll_timer);
+               start_int_poll_timer(ctrl, 10);
+               return 0;
+       }
+
+       /* Installs the interrupt handler */
+       retval = request_irq(irq, pcie_isr, IRQF_SHARED, MY_NAME, ctrl);
+       if (retval)
+               err("Cannot get irq %d for the hotplug controller\n", irq);
+       return retval;
+}
+
+static inline void pciehp_free_irq(struct controller *ctrl)
+{
+       if (pciehp_poll_mode)
+               del_timer_sync(&ctrl->poll_timer);
+       else
+               free_irq(ctrl->pci_dev->irq, ctrl);
+}
+
 static inline int pcie_wait_cmd(struct controller *ctrl)
 {
        int retval = 0;
@@ -242,17 +268,15 @@ static inline int pcie_wait_cmd(struct controller *ctrl)
 
 /**
  * pcie_write_cmd - Issue controller command
- * @slot: slot to which the command is issued
+ * @ctrl: controller to which the command is issued
  * @cmd:  command value written to slot control register
  * @mask: bitmask of slot control register to be modified
  */
-static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
+static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
 {
-       struct controller *ctrl = slot->ctrl;
        int retval = 0;
        u16 slot_status;
        u16 slot_ctrl;
-       unsigned long flags;
 
        mutex_lock(&ctrl->ctrl_lock);
 
@@ -270,24 +294,24 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
                    __func__);
        }
 
-       spin_lock_irqsave(&ctrl->lock, flags);
        retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
        if (retval) {
                err("%s: Cannot read SLOTCTRL register\n", __func__);
-               goto out_spin_unlock;
+               goto out;
        }
 
        slot_ctrl &= ~mask;
-       slot_ctrl |= ((cmd & mask) | CMD_CMPL_INTR_ENABLE);
+       slot_ctrl |= (cmd & mask);
+       /* Don't enable command completed if caller is changing it. */
+       if (!(mask & CMD_CMPL_INTR_ENABLE))
+               slot_ctrl |= CMD_CMPL_INTR_ENABLE;
 
        ctrl->cmd_busy = 1;
+       smp_mb();
        retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl);
        if (retval)
                err("%s: Cannot write to SLOTCTRL register\n", __func__);
 
- out_spin_unlock:
-       spin_unlock_irqrestore(&ctrl->lock, flags);
-
        /*
         * Wait for command completion.
         */
@@ -467,12 +491,7 @@ static int hpc_toggle_emi(struct slot *slot)
 
        slot_cmd = EMI_CTRL;
        cmd_mask = EMI_CTRL;
-       if (!pciehp_poll_mode) {
-               slot_cmd = slot_cmd | HP_INTR_ENABLE;
-               cmd_mask = cmd_mask | HP_INTR_ENABLE;
-       }
-
-       rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
+       rc = pcie_write_cmd(slot->ctrl, slot_cmd, cmd_mask);
        slot->last_emi_toggle = get_seconds();
 
        return rc;
@@ -499,12 +518,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
                default:
                        return -1;
        }
-       if (!pciehp_poll_mode) {
-               slot_cmd = slot_cmd | HP_INTR_ENABLE;
-               cmd_mask = cmd_mask | HP_INTR_ENABLE;
-       }
-
-       rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
+       rc = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
        dbg("%s: SLOTCTRL %x write cmd %x\n",
            __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 
@@ -519,13 +533,7 @@ static void hpc_set_green_led_on(struct slot *slot)
 
        slot_cmd = 0x0100;
        cmd_mask = PWR_LED_CTRL;
-       if (!pciehp_poll_mode) {
-               slot_cmd = slot_cmd | HP_INTR_ENABLE;
-               cmd_mask = cmd_mask | HP_INTR_ENABLE;
-       }
-
-       pcie_write_cmd(slot, slot_cmd, cmd_mask);
-
+       pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
        dbg("%s: SLOTCTRL %x write cmd %x\n",
            __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 }
@@ -538,12 +546,7 @@ static void hpc_set_green_led_off(struct slot *slot)
 
        slot_cmd = 0x0300;
        cmd_mask = PWR_LED_CTRL;
-       if (!pciehp_poll_mode) {
-               slot_cmd = slot_cmd | HP_INTR_ENABLE;
-               cmd_mask = cmd_mask | HP_INTR_ENABLE;
-       }
-
-       pcie_write_cmd(slot, slot_cmd, cmd_mask);
+       pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
        dbg("%s: SLOTCTRL %x write cmd %x\n",
            __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 }
@@ -556,23 +559,19 @@ static void hpc_set_green_led_blink(struct slot *slot)
 
        slot_cmd = 0x0200;
        cmd_mask = PWR_LED_CTRL;
-       if (!pciehp_poll_mode) {
-               slot_cmd = slot_cmd | HP_INTR_ENABLE;
-               cmd_mask = cmd_mask | HP_INTR_ENABLE;
-       }
-
-       pcie_write_cmd(slot, slot_cmd, cmd_mask);
-
+       pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
        dbg("%s: SLOTCTRL %x write cmd %x\n",
            __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
 }
 
 static void hpc_release_ctlr(struct controller *ctrl)
 {
-       if (pciehp_poll_mode)
-               del_timer(&ctrl->poll_timer);
-       else
-               free_irq(ctrl->pci_dev->irq, ctrl);
+       /* Mask Hot-plug Interrupt Enable */
+       if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE))
+               err("%s: Cannot mask hotplut interrupt enable\n", __func__);
+
+       /* Free interrupt handler or interrupt polling timer */
+       pciehp_free_irq(ctrl);
 
        /*
         * If this is the last controller to be released, destroy the
@@ -612,19 +611,13 @@ static int hpc_power_on_slot(struct slot * slot)
        cmd_mask = PWR_CTRL;
        /* Enable detection that we turned off at slot power-off time */
        if (!pciehp_poll_mode) {
-               slot_cmd = slot_cmd |
-                          PWR_FAULT_DETECT_ENABLE |
-                          MRL_DETECT_ENABLE |
-                          PRSN_DETECT_ENABLE |
-                          HP_INTR_ENABLE;
-               cmd_mask = cmd_mask |
-                          PWR_FAULT_DETECT_ENABLE |
-                          MRL_DETECT_ENABLE |
-                          PRSN_DETECT_ENABLE |
-                          HP_INTR_ENABLE;
+               slot_cmd |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
+                            PRSN_DETECT_ENABLE);
+               cmd_mask |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
+                            PRSN_DETECT_ENABLE);
        }
 
-       retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
+       retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
 
        if (retval) {
                err("%s: Write %x command failed!\n", __func__, slot_cmd);
@@ -697,18 +690,13 @@ static int hpc_power_off_slot(struct slot * slot)
         * till the slot is powered on again.
         */
        if (!pciehp_poll_mode) {
-               slot_cmd = (slot_cmd &
-                           ~PWR_FAULT_DETECT_ENABLE &
-                           ~MRL_DETECT_ENABLE &
-                           ~PRSN_DETECT_ENABLE) | HP_INTR_ENABLE;
-               cmd_mask = cmd_mask |
-                          PWR_FAULT_DETECT_ENABLE |
-                          MRL_DETECT_ENABLE |
-                          PRSN_DETECT_ENABLE |
-                          HP_INTR_ENABLE;
+               slot_cmd &= ~(PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
+                             PRSN_DETECT_ENABLE);
+               cmd_mask |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
+                            PRSN_DETECT_ENABLE);
        }
 
-       retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
+       retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
        if (retval) {
                err("%s: Write command failed!\n", __func__);
                retval = -1;
@@ -733,139 +721,56 @@ static int hpc_power_off_slot(struct slot * slot)
 static irqreturn_t pcie_isr(int irq, void *dev_id)
 {
        struct controller *ctrl = (struct controller *)dev_id;
-       u16 slot_status, intr_detect, intr_loc;
-       u16 temp_word;
-       int hp_slot = 0;        /* only 1 slot per PCI Express port */
-       int rc = 0;
-       unsigned long flags;
-
-       rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-       if (rc) {
-               err("%s: Cannot read SLOTSTATUS register\n", __func__);
-               return IRQ_NONE;
-       }
-
-       intr_detect = (ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED |
-                      MRL_SENS_CHANGED | PRSN_DETECT_CHANGED | CMD_COMPLETED);
-
-       intr_loc = slot_status & intr_detect;
-
-       /* Check to see if it was our interrupt */
-       if ( !intr_loc )
-               return IRQ_NONE;
+       u16 detected, intr_loc;
 
-       dbg("%s: intr_loc %x\n", __func__, intr_loc);
-       /* Mask Hot-plug Interrupt Enable */
-       if (!pciehp_poll_mode) {
-               spin_lock_irqsave(&ctrl->lock, flags);
-               rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-               if (rc) {
-                       err("%s: Cannot read SLOT_CTRL register\n",
-                           __func__);
-                       spin_unlock_irqrestore(&ctrl->lock, flags);
+       /*
+        * In order to guarantee that all interrupt events are
+        * serviced, we need to re-inspect Slot Status register after
+        * clearing what is presumed to be the last pending interrupt.
+        */
+       intr_loc = 0;
+       do {
+               if (pciehp_readw(ctrl, SLOTSTATUS, &detected)) {
+                       err("%s: Cannot read SLOTSTATUS\n", __func__);
                        return IRQ_NONE;
                }
 
-               dbg("%s: pciehp_readw(SLOTCTRL) with value %x\n",
-                   __func__, temp_word);
-               temp_word = (temp_word & ~HP_INTR_ENABLE &
-                            ~CMD_CMPL_INTR_ENABLE) | 0x00;
-               rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
-               if (rc) {
-                       err("%s: Cannot write to SLOTCTRL register\n",
-                           __func__);
-                       spin_unlock_irqrestore(&ctrl->lock, flags);
+               detected &= (ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED |
+                            MRL_SENS_CHANGED | PRSN_DETECT_CHANGED |
+                            CMD_COMPLETED);
+               intr_loc |= detected;
+               if (!intr_loc)
                        return IRQ_NONE;
-               }
-               spin_unlock_irqrestore(&ctrl->lock, flags);
-
-               rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-               if (rc) {
-                       err("%s: Cannot read SLOT_STATUS register\n",
-                           __func__);
+               if (pciehp_writew(ctrl, SLOTSTATUS, detected)) {
+                       err("%s: Cannot write to SLOTSTATUS\n", __func__);
                        return IRQ_NONE;
                }
-               dbg("%s: pciehp_readw(SLOTSTATUS) with value %x\n",
-                   __func__, slot_status);
+       } while (detected);
 
-               /* Clear command complete interrupt caused by this write */
-               temp_word = 0x1f;
-               rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
-               if (rc) {
-                       err("%s: Cannot write to SLOTSTATUS register\n",
-                           __func__);
-                       return IRQ_NONE;
-               }
-       }
+       dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc);
 
+       /* Check Command Complete Interrupt Pending */
        if (intr_loc & CMD_COMPLETED) {
-               /*
-                * Command Complete Interrupt Pending
-                */
                ctrl->cmd_busy = 0;
+               smp_mb();
                wake_up_interruptible(&ctrl->queue);
        }
 
+       /* Check MRL Sensor Changed */
        if (intr_loc & MRL_SENS_CHANGED)
-               pciehp_handle_switch_change(hp_slot, ctrl);
+               pciehp_handle_switch_change(0, ctrl);
 
+       /* Check Attention Button Pressed */
        if (intr_loc & ATTN_BUTTN_PRESSED)
-               pciehp_handle_attention_button(hp_slot, ctrl);
+               pciehp_handle_attention_button(0, ctrl);
 
+       /* Check Presence Detect Changed */
        if (intr_loc & PRSN_DETECT_CHANGED)
-               pciehp_handle_presence_change(hp_slot, ctrl);
+               pciehp_handle_presence_change(0, ctrl);
 
+       /* Check Power Fault Detected */
        if (intr_loc & PWR_FAULT_DETECTED)
-               pciehp_handle_power_fault(hp_slot, ctrl);
-
-       /* Clear all events after serving them */
-       temp_word = 0x1F;
-       rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
-       if (rc) {
-               err("%s: Cannot write to SLOTSTATUS register\n", __func__);
-               return IRQ_NONE;
-       }
-       /* Unmask Hot-plug Interrupt Enable */
-       if (!pciehp_poll_mode) {
-               spin_lock_irqsave(&ctrl->lock, flags);
-               rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-               if (rc) {
-                       err("%s: Cannot read SLOTCTRL register\n",
-                           __func__);
-                       spin_unlock_irqrestore(&ctrl->lock, flags);
-                       return IRQ_NONE;
-               }
-
-               dbg("%s: Unmask Hot-plug Interrupt Enable\n", __func__);
-               temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
-
-               rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
-               if (rc) {
-                       err("%s: Cannot write to SLOTCTRL register\n",
-                           __func__);
-                       spin_unlock_irqrestore(&ctrl->lock, flags);
-                       return IRQ_NONE;
-               }
-               spin_unlock_irqrestore(&ctrl->lock, flags);
-
-               rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-               if (rc) {
-                       err("%s: Cannot read SLOT_STATUS register\n",
-                           __func__);
-                       return IRQ_NONE;
-               }
-
-               /* Clear command complete interrupt caused by this write */
-               temp_word = 0x1F;
-               rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
-               if (rc) {
-                       err("%s: Cannot write to SLOTSTATUS failed\n",
-                           __func__);
-                       return IRQ_NONE;
-               }
-               dbg("%s: pciehp_writew(SLOTSTATUS) with value %x\n",
-                   __func__, temp_word);
-       }
+               pciehp_handle_power_fault(0, ctrl);
 
        return IRQ_HANDLED;
 }
@@ -1052,7 +957,7 @@ static struct hpc_ops pciehp_hpc_ops = {
 };
 
 #ifdef CONFIG_ACPI
-int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
+static int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
 {
        acpi_status status;
        acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
@@ -1112,7 +1017,7 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
                        break;
        }
 
-       err("Cannot get control of hotplug hardware for pci %s\n",
+       dbg("Cannot get control of hotplug hardware for pci %s\n",
                        pci_name(dev));
 
        kfree(string.pointer);
@@ -1123,45 +1028,9 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
 static int pcie_init_hardware_part1(struct controller *ctrl,
                                    struct pcie_device *dev)
 {
-       int rc;
-       u16 temp_word;
-       u32 slot_cap;
-       u16 slot_status;
-
-       rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
-       if (rc) {
-               err("%s: Cannot read SLOTCAP register\n", __func__);
-               return -1;
-       }
-
        /* Mask Hot-plug Interrupt Enable */
-       rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-       if (rc) {
-               err("%s: Cannot read SLOTCTRL register\n", __func__);
-               return -1;
-       }
-
-       dbg("%s: SLOTCTRL %x value read %x\n",
-           __func__, ctrl->cap_base + SLOTCTRL, temp_word);
-       temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |
-               0x00;
-
-       rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
-       if (rc) {
-               err("%s: Cannot write to SLOTCTRL register\n", __func__);
-               return -1;
-       }
-
-       rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-       if (rc) {
-               err("%s: Cannot read SLOTSTATUS register\n", __func__);
-               return -1;
-       }
-
-       temp_word = 0x1F; /* Clear all events */
-       rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
-       if (rc) {
-               err("%s: Cannot write to SLOTSTATUS register\n", __func__);
+       if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE)) {
+               err("%s: Cannot mask hotplug interrupt enable\n", __func__);
                return -1;
        }
        return 0;
@@ -1169,205 +1038,125 @@ static int pcie_init_hardware_part1(struct controller *ctrl,
 
 int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
 {
-       int rc;
-       u16 temp_word;
-       u16 intr_enable = 0;
-       u32 slot_cap;
-       u16 slot_status;
+       u16 cmd, mask;
 
-       rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-       if (rc) {
-               err("%s: Cannot read SLOTCTRL register\n", __func__);
-               goto abort;
-       }
-
-       intr_enable = intr_enable | PRSN_DETECT_ENABLE;
-
-       rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
-       if (rc) {
-               err("%s: Cannot read SLOTCAP register\n", __func__);
-               goto abort;
+       /*
+        * We need to clear all events before enabling hotplug interrupt
+        * notification mechanism in order for hotplug controler to
+        * generate interrupts.
+        */
+       if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) {
+               err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
+               return -1;
        }
 
-       if (ATTN_BUTTN(slot_cap))
-               intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
-
-       if (POWER_CTRL(slot_cap))
-               intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
-
-       if (MRL_SENS(slot_cap))
-               intr_enable = intr_enable | MRL_DETECT_ENABLE;
+       cmd = PRSN_DETECT_ENABLE;
+       if (ATTN_BUTTN(ctrl))
+               cmd |= ATTN_BUTTN_ENABLE;
+       if (POWER_CTRL(ctrl))
+               cmd |= PWR_FAULT_DETECT_ENABLE;
+       if (MRL_SENS(ctrl))
+               cmd |= MRL_DETECT_ENABLE;
+       if (!pciehp_poll_mode)
+               cmd |= HP_INTR_ENABLE;
 
-       temp_word = (temp_word & ~intr_enable) | intr_enable;
+       mask = PRSN_DETECT_ENABLE | ATTN_BUTTN_ENABLE |
+               PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | HP_INTR_ENABLE;
 
-       if (pciehp_poll_mode) {
-               temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
-       } else {
-               temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
-       }
-
-       /*
-        * Unmask Hot-plug Interrupt Enable for the interrupt
-        * notification mechanism case.
-        */
-       rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
-       if (rc) {
-               err("%s: Cannot write to SLOTCTRL register\n", __func__);
+       if (pcie_write_cmd(ctrl, cmd, mask)) {
+               err("%s: Cannot enable software notification\n", __func__);
                goto abort;
        }
-       rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-       if (rc) {
-               err("%s: Cannot read SLOTSTATUS register\n", __func__);
-               goto abort_disable_intr;
-       }
-
-       temp_word =  0x1F; /* Clear all events */
-       rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
-       if (rc) {
-               err("%s: Cannot write to SLOTSTATUS register\n", __func__);
-               goto abort_disable_intr;
-       }
 
-       if (pciehp_force) {
+       if (pciehp_force)
                dbg("Bypassing BIOS check for pciehp use on %s\n",
                                pci_name(ctrl->pci_dev));
-       } else {
-               rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
-               if (rc)
-                       goto abort_disable_intr;
-       }
+       else if (pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev))
+               goto abort_disable_intr;
 
        return 0;
 
        /* We end up here for the many possible ways to fail this API. */
 abort_disable_intr:
-       rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
-       if (!rc) {
-               temp_word &= ~(intr_enable | HP_INTR_ENABLE);
-               rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
-       }
-       if (rc)
+       if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE))
                err("%s : disabling interrupts failed\n", __func__);
 abort:
        return -1;
 }
 
-int pcie_init(struct controller *ctrl, struct pcie_device *dev)
+static inline void dbg_ctrl(struct controller *ctrl)
 {
-       int rc;
-       u16 cap_reg;
-       u32 slot_cap;
-       int cap_base;
-       u16 slot_status, slot_ctrl;
-       struct pci_dev *pdev;
-
-       pdev = dev->port;
-       ctrl->pci_dev = pdev;   /* save pci_dev in context */
-
-       dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n",
-                       __func__, pdev->vendor, pdev->device);
+       int i;
+       u16 reg16;
+       struct pci_dev *pdev = ctrl->pci_dev;
 
-       cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
-       if (cap_base == 0) {
-               dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __func__);
-               goto abort;
-       }
+       if (!pciehp_debug)
+               return;
 
-       ctrl->cap_base = cap_base;
+       dbg("Hotplug Controller:\n");
+       dbg("  Seg/Bus/Dev/Func/IRQ : %s IRQ %d\n", pci_name(pdev), pdev->irq);
+       dbg("  Vendor ID            : 0x%04x\n", pdev->vendor);
+       dbg("  Device ID            : 0x%04x\n", pdev->device);
+       dbg("  Subsystem ID         : 0x%04x\n", pdev->subsystem_device);
+       dbg("  Subsystem Vendor ID  : 0x%04x\n", pdev->subsystem_vendor);
+       dbg("  PCIe Cap offset      : 0x%02x\n", ctrl->cap_base);
+       for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+               if (!pci_resource_len(pdev, i))
+                       continue;
+               dbg("  PCI resource [%d]     : 0x%llx@0x%llx\n", i,
+                   (unsigned long long)pci_resource_len(pdev, i),
+                   (unsigned long long)pci_resource_start(pdev, i));
+       }
+       dbg("Slot Capabilities      : 0x%08x\n", ctrl->slot_cap);
+       dbg("  Physical Slot Number : %d\n", ctrl->first_slot);
+       dbg("  Attention Button     : %3s\n", ATTN_BUTTN(ctrl) ? "yes" : "no");
+       dbg("  Power Controller     : %3s\n", POWER_CTRL(ctrl) ? "yes" : "no");
+       dbg("  MRL Sensor           : %3s\n", MRL_SENS(ctrl)   ? "yes" : "no");
+       dbg("  Attention Indicator  : %3s\n", ATTN_LED(ctrl)   ? "yes" : "no");
+       dbg("  Power Indicator      : %3s\n", PWR_LED(ctrl)    ? "yes" : "no");
+       dbg("  Hot-Plug Surprise    : %3s\n", HP_SUPR_RM(ctrl) ? "yes" : "no");
+       dbg("  EMI Present          : %3s\n", EMI(ctrl)        ? "yes" : "no");
+       pciehp_readw(ctrl, SLOTSTATUS, &reg16);
+       dbg("Slot Status            : 0x%04x\n", reg16);
+       pciehp_readw(ctrl, SLOTSTATUS, &reg16);
+       dbg("Slot Control           : 0x%04x\n", reg16);
+}
 
-       dbg("%s: pcie_cap_base %x\n", __func__, cap_base);
+int pcie_init(struct controller *ctrl, struct pcie_device *dev)
+{
+       u32 slot_cap;
+       struct pci_dev *pdev = dev->port;
 
-       rc = pciehp_readw(ctrl, CAPREG, &cap_reg);
-       if (rc) {
-               err("%s: Cannot read CAPREG register\n", __func__);
-               goto abort;
-       }
-       dbg("%s: CAPREG offset %x cap_reg %x\n",
-           __func__, ctrl->cap_base + CAPREG, cap_reg);
-
-       if (((cap_reg & SLOT_IMPL) == 0) ||
-           (((cap_reg & DEV_PORT_TYPE) != 0x0040)
-               && ((cap_reg & DEV_PORT_TYPE) != 0x0060))) {
-               dbg("%s : This is not a root port or the port is not "
-                   "connected to a slot\n", __func__);
+       ctrl->pci_dev = pdev;
+       ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+       if (!ctrl->cap_base) {
+               err("%s: Cannot find PCI Express capability\n", __func__);
                goto abort;
        }
-
-       rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
-       if (rc) {
+       if (pciehp_readl(ctrl, SLOTCAP, &slot_cap)) {
                err("%s: Cannot read SLOTCAP register\n", __func__);
                goto abort;
        }
-       dbg("%s: SLOTCAP offset %x slot_cap %x\n",
-           __func__, ctrl->cap_base + SLOTCAP, slot_cap);
-
-       if (!(slot_cap & HP_CAP)) {
-               dbg("%s : This slot is not hot-plug capable\n", __func__);
-               goto abort;
-       }
-       /* For debugging purpose */
-       rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
-       if (rc) {
-               err("%s: Cannot read SLOTSTATUS register\n", __func__);
-               goto abort;
-       }
-       dbg("%s: SLOTSTATUS offset %x slot_status %x\n",
-           __func__, ctrl->cap_base + SLOTSTATUS, slot_status);
-
-       rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
-       if (rc) {
-               err("%s: Cannot read SLOTCTRL register\n", __func__);
-               goto abort;
-       }
-       dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
-           __func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
-
-       for (rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
-               if (pci_resource_len(pdev, rc) > 0)
-                       dbg("pci resource[%d] start=0x%llx(len=0x%llx)\n", rc,
-                           (unsigned long long)pci_resource_start(pdev, rc),
-                           (unsigned long long)pci_resource_len(pdev, rc));
-
-       info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
-            pdev->vendor, pdev->device,
-            pdev->subsystem_vendor, pdev->subsystem_device);
 
+       ctrl->slot_cap = slot_cap;
+       ctrl->first_slot = slot_cap >> 19;
+       ctrl->slot_device_offset = 0;
+       ctrl->num_slots = 1;
+       ctrl->hpc_ops = &pciehp_hpc_ops;
        mutex_init(&ctrl->crit_sect);
        mutex_init(&ctrl->ctrl_lock);
-       spin_lock_init(&ctrl->lock);
-
-       /* setup wait queue */
        init_waitqueue_head(&ctrl->queue);
+       dbg_ctrl(ctrl);
 
-       /* return PCI Controller Info */
-       ctrl->slot_device_offset = 0;
-       ctrl->num_slots = 1;
-       ctrl->first_slot = slot_cap >> 19;
-       ctrl->ctrlcap = slot_cap & 0x0000007f;
+       info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
+            pdev->vendor, pdev->device,
+            pdev->subsystem_vendor, pdev->subsystem_device);
 
-       rc = pcie_init_hardware_part1(ctrl, dev);
-       if (rc)
+       if (pcie_init_hardware_part1(ctrl, dev))
                goto abort;
 
-       if (pciehp_poll_mode) {
-               /* Install interrupt polling timer. Start with 10 sec delay */
-               init_timer(&ctrl->poll_timer);
-               start_int_poll_timer(ctrl, 10);
-       } else {
-               /* Installs the interrupt handler */
-               rc = request_irq(ctrl->pci_dev->irq, pcie_isr, IRQF_SHARED,
-                                MY_NAME, (void *)ctrl);
-               dbg("%s: request_irq %d for hpc%d (returns %d)\n",
-                   __func__, ctrl->pci_dev->irq,
-                   atomic_read(&pciehp_num_controllers), rc);
-               if (rc) {
-                       err("Can't get irq %d for the hotplug controller\n",
-                           ctrl->pci_dev->irq);
-                       goto abort;
-               }
-       }
-       dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number,
-               PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq);
+       if (pciehp_request_irq(ctrl))
+               goto abort;
 
        /*
         * If this is the first controller to be initialized,
@@ -1376,21 +1165,17 @@ int pcie_init(struct controller *ctrl, struct pcie_device *dev)
        if (atomic_add_return(1, &pciehp_num_controllers) == 1) {
                pciehp_wq = create_singlethread_workqueue("pciehpd");
                if (!pciehp_wq) {
-                       rc = -ENOMEM;
                        goto abort_free_irq;
                }
        }
 
-       rc = pcie_init_hardware_part2(ctrl, dev);
-       if (rc == 0) {
-               ctrl->hpc_ops = &pciehp_hpc_ops;
-               return 0;
-       }
+       if (pcie_init_hardware_part2(ctrl, dev))
+               goto abort_free_irq;
+
+       return 0;
+
 abort_free_irq:
-       if (pciehp_poll_mode)
-               del_timer_sync(&ctrl->poll_timer);
-       else
-               free_irq(ctrl->pci_dev->irq, ctrl);
+       pciehp_free_irq(ctrl);
 abort:
        return -1;
 }
index 43816d4b3c435bf37a23740e4855551827059520..1648076600fc195a1c6a71a3f9ae444423400194 100644 (file)
@@ -39,6 +39,7 @@
 int shpchp_debug;
 int shpchp_poll_mode;
 int shpchp_poll_time;
+int shpchp_slot_with_bus;
 struct workqueue_struct *shpchp_wq;
 
 #define DRIVER_VERSION "0.4"
@@ -52,9 +53,11 @@ MODULE_LICENSE("GPL");
 module_param(shpchp_debug, bool, 0644);
 module_param(shpchp_poll_mode, bool, 0644);
 module_param(shpchp_poll_time, int, 0644);
+module_param(shpchp_slot_with_bus, bool, 0644);
 MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not");
 MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not");
 MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds");
+MODULE_PARM_DESC(shpchp_slot_with_bus, "Use bus number in the slot name");
 
 #define SHPC_MODULE_NAME "shpchp"
 
@@ -100,8 +103,12 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
 
 static void make_slot_name(struct slot *slot)
 {
-       snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
-                slot->bus, slot->number);
+       if (shpchp_slot_with_bus)
+               snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
+                        slot->bus, slot->number);
+       else
+               snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d",
+                        slot->number);
 }
 
 static int init_slots(struct controller *ctrl)
index 26938da8f4380c5fd0bdb1786c71f8adb8418046..8c61304cbb37e8b9f32343c0fb93cd73bd276d27 100644 (file)
@@ -123,7 +123,7 @@ static void msix_flush_writes(unsigned int irq)
        }
 }
 
-static void msi_set_mask_bit(unsigned int irq, int flag)
+static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag)
 {
        struct msi_desc *entry;
 
@@ -137,8 +137,8 @@ static void msi_set_mask_bit(unsigned int irq, int flag)
 
                        pos = (long)entry->mask_base;
                        pci_read_config_dword(entry->dev, pos, &mask_bits);
-                       mask_bits &= ~(1);
-                       mask_bits |= flag;
+                       mask_bits &= ~(mask);
+                       mask_bits |= flag & mask;
                        pci_write_config_dword(entry->dev, pos, mask_bits);
                } else {
                        msi_set_enable(entry->dev, !flag);
@@ -241,13 +241,13 @@ void write_msi_msg(unsigned int irq, struct msi_msg *msg)
 
 void mask_msi_irq(unsigned int irq)
 {
-       msi_set_mask_bit(irq, 1);
+       msi_set_mask_bits(irq, 1, 1);
        msix_flush_writes(irq);
 }
 
 void unmask_msi_irq(unsigned int irq)
 {
-       msi_set_mask_bit(irq, 0);
+       msi_set_mask_bits(irq, 1, 0);
        msix_flush_writes(irq);
 }
 
@@ -291,7 +291,8 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
        msi_set_enable(dev, 0);
        write_msi_msg(dev->irq, &entry->msg);
        if (entry->msi_attrib.maskbit)
-               msi_set_mask_bit(dev->irq, entry->msi_attrib.masked);
+               msi_set_mask_bits(dev->irq, entry->msi_attrib.maskbits_mask,
+                                 entry->msi_attrib.masked);
 
        pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
        control &= ~(PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE);
@@ -315,7 +316,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
 
        list_for_each_entry(entry, &dev->msi_list, list) {
                write_msi_msg(entry->irq, &entry->msg);
-               msi_set_mask_bit(entry->irq, entry->msi_attrib.masked);
+               msi_set_mask_bits(entry->irq, 1, entry->msi_attrib.masked);
        }
 
        BUG_ON(list_empty(&dev->msi_list));
@@ -382,6 +383,7 @@ static int msi_capability_init(struct pci_dev *dev)
                pci_write_config_dword(dev,
                        msi_mask_bits_reg(pos, is_64bit_address(control)),
                        maskbits);
+               entry->msi_attrib.maskbits_mask = temp;
        }
        list_add_tail(&entry->list, &dev->msi_list);
 
@@ -569,10 +571,9 @@ int pci_enable_msi(struct pci_dev* dev)
 }
 EXPORT_SYMBOL(pci_enable_msi);
 
-void pci_disable_msi(struct pci_dev* dev)
+void pci_msi_shutdown(struct pci_dev* dev)
 {
        struct msi_desc *entry;
-       int default_irq;
 
        if (!pci_msi_enable || !dev || !dev->msi_enabled)
                return;
@@ -583,15 +584,31 @@ void pci_disable_msi(struct pci_dev* dev)
 
        BUG_ON(list_empty(&dev->msi_list));
        entry = list_entry(dev->msi_list.next, struct msi_desc, list);
-       if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) {
-               return;
+       /* Return the the pci reset with msi irqs unmasked */
+       if (entry->msi_attrib.maskbit) {
+               u32 mask = entry->msi_attrib.maskbits_mask;
+               msi_set_mask_bits(dev->irq, mask, ~mask);
        }
-
-       default_irq = entry->msi_attrib.default_irq;
-       msi_free_irqs(dev);
+       if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI)
+               return;
 
        /* Restore dev->irq to its default pin-assertion irq */
-       dev->irq = default_irq;
+       dev->irq = entry->msi_attrib.default_irq;
+}
+void pci_disable_msi(struct pci_dev* dev)
+{
+       struct msi_desc *entry;
+
+       if (!pci_msi_enable || !dev || !dev->msi_enabled)
+               return;
+
+       pci_msi_shutdown(dev);
+
+       entry = list_entry(dev->msi_list.next, struct msi_desc, list);
+       if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI)
+               return;
+
+       msi_free_irqs(dev);
 }
 EXPORT_SYMBOL(pci_disable_msi);
 
@@ -684,7 +701,7 @@ static void msix_free_all_irqs(struct pci_dev *dev)
        msi_free_irqs(dev);
 }
 
-void pci_disable_msix(struct pci_dev* dev)
+void pci_msix_shutdown(struct pci_dev* dev)
 {
        if (!pci_msi_enable || !dev || !dev->msix_enabled)
                return;
@@ -692,6 +709,13 @@ void pci_disable_msix(struct pci_dev* dev)
        msix_set_enable(dev, 0);
        pci_intx_for_msi(dev, 1);
        dev->msix_enabled = 0;
+}
+void pci_disable_msix(struct pci_dev* dev)
+{
+       if (!pci_msi_enable || !dev || !dev->msix_enabled)
+               return;
+
+       pci_msix_shutdown(dev);
 
        msix_free_all_irqs(dev);
 }
index e8d94fafc2804e74fddd9c66eee9fac29a11883b..72cf61ed8f966d20f99c32d6acd77424e419ee69 100644 (file)
@@ -360,6 +360,8 @@ static void pci_device_shutdown(struct device *dev)
 
        if (drv && drv->shutdown)
                drv->shutdown(pci_dev);
+       pci_msi_shutdown(pci_dev);
+       pci_msix_shutdown(pci_dev);
 }
 
 /**
index 25b04fb2517d486137b18cdc619de14075e57ad2..5a0c6ad53f8ee0f8b8ce9ee978394b850b895c59 100644 (file)
@@ -33,7 +33,7 @@ source "drivers/pci/pcie/aer/Kconfig"
 config PCIEASPM
        bool "PCI Express ASPM support(Experimental)"
        depends on PCI && EXPERIMENTAL && PCIEPORTBUS
-       default y
+       default n
        help
          This enables PCI Express ASPM (Active State Power Management) and
          Clock Power Management. ASPM supports state L0/L0s/L1.
index f991359f0c3689d292e749b798ef2888f8af7934..4a55bf380957fd5142f0dd0a8dfa9c39af6d73e8 100644 (file)
@@ -842,11 +842,14 @@ static void set_pcie_port_type(struct pci_dev *pdev)
  * reading the dword at 0x100 which must either be 0 or a valid extended
  * capability header.
  */
-int pci_cfg_space_size(struct pci_dev *dev)
+int pci_cfg_space_size_ext(struct pci_dev *dev, unsigned check_exp_pcix)
 {
        int pos;
        u32 status;
 
+       if (!check_exp_pcix)
+               goto skip;
+
        pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
        if (!pos) {
                pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
@@ -858,6 +861,7 @@ int pci_cfg_space_size(struct pci_dev *dev)
                        goto fail;
        }
 
+ skip:
        if (pci_read_config_dword(dev, 256, &status) != PCIBIOS_SUCCESSFUL)
                goto fail;
        if (status == 0xffffffff)
@@ -869,6 +873,11 @@ int pci_cfg_space_size(struct pci_dev *dev)
        return PCI_CFG_SPACE_SIZE;
 }
 
+int pci_cfg_space_size(struct pci_dev *dev)
+{
+       return pci_cfg_space_size_ext(dev, 1);
+}
+
 static void pci_release_bus_bridge_dev(struct device *dev)
 {
        kfree(dev);
@@ -964,7 +973,6 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
        dev->dev.release = pci_release_dev;
        pci_dev_get(dev);
 
-       set_dev_node(&dev->dev, pcibus_to_node(bus));
        dev->dev.dma_mask = &dev->dma_mask;
        dev->dev.dma_parms = &dev->dma_parms;
        dev->dev.coherent_dma_mask = 0xffffffffull;
@@ -1080,6 +1088,10 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
        return max;
 }
 
+void __attribute__((weak)) set_pci_bus_resources_arch_default(struct pci_bus *b)
+{
+}
+
 struct pci_bus * pci_create_bus(struct device *parent,
                int bus, struct pci_ops *ops, void *sysdata)
 {
@@ -1119,6 +1131,9 @@ struct pci_bus * pci_create_bus(struct device *parent,
                goto dev_reg_err;
        b->bridge = get_device(dev);
 
+       if (!parent)
+               set_dev_node(b->bridge, pcibus_to_node(b));
+
        b->dev.class = &pcibus_class;
        b->dev.parent = b->bridge;
        sprintf(b->dev.bus_id, "%04x:%02x", pci_domain_nr(b), bus);
@@ -1136,6 +1151,8 @@ struct pci_bus * pci_create_bus(struct device *parent,
        b->resource[0] = &ioport_resource;
        b->resource[1] = &iomem_resource;
 
+       set_pci_bus_resources_arch_default(b);
+
        return b;
 
 dev_create_file_err:
index ef18fcd641e2c478927e5e6f29505d31380b75ae..963a97642ae9101a7454c7b0b3c0dbcc95f8240e 100644 (file)
@@ -293,6 +293,7 @@ static int proc_bus_pci_release(struct inode *inode, struct file *file)
 #endif /* HAVE_PCI_MMAP */
 
 static const struct file_operations proc_bus_pci_operations = {
+       .owner          = THIS_MODULE,
        .llseek         = proc_bus_pci_lseek,
        .read           = proc_bus_pci_read,
        .write          = proc_bus_pci_write,
@@ -406,11 +407,10 @@ int pci_proc_attach_device(struct pci_dev *dev)
        }
 
        sprintf(name, "%02x.%x", PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
-       e = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, bus->procdir);
+       e = proc_create_data(name, S_IFREG | S_IRUGO | S_IWUSR, bus->procdir,
+                            &proc_bus_pci_operations, dev);
        if (!e)
                return -ENOMEM;
-       e->proc_fops = &proc_bus_pci_operations;
-       e->data = dev;
        e->size = dev->cfg_size;
        dev->procent = e;
 
@@ -462,6 +462,7 @@ static int proc_bus_pci_dev_open(struct inode *inode, struct file *file)
        return seq_open(file, &proc_bus_pci_devices_op);
 }
 static const struct file_operations proc_bus_pci_dev_operations = {
+       .owner          = THIS_MODULE,
        .open           = proc_bus_pci_dev_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -470,12 +471,10 @@ static const struct file_operations proc_bus_pci_dev_operations = {
 
 static int __init pci_proc_init(void)
 {
-       struct proc_dir_entry *entry;
        struct pci_dev *dev = NULL;
-       proc_bus_pci_dir = proc_mkdir("pci", proc_bus);
-       entry = create_proc_entry("devices", 0, proc_bus_pci_dir);
-       if (entry)
-               entry->proc_fops = &proc_bus_pci_dev_operations;
+       proc_bus_pci_dir = proc_mkdir("bus/pci", NULL);
+       proc_create("devices", 0, proc_bus_pci_dir,
+                   &proc_bus_pci_dev_operations);
        proc_initialized = 1;
        while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
                pci_proc_attach_device(dev);
index 06a85d7d5aa2fecb63edd53fb528aeb2d7ad828c..36379535f9daf17f8cb86a779cab491203afa9c1 100644 (file)
@@ -402,15 +402,6 @@ EXPORT_SYMBOL(pcmcia_replace_cis);
     
 ======================================================================*/
 
-static inline u16 cis_get_u16(void *ptr)
-{
-       return le16_to_cpu(get_unaligned((__le16 *) ptr));
-}
-static inline u32 cis_get_u32(void *ptr)
-{
-       return le32_to_cpu(get_unaligned((__le32 *) ptr));
-}
-
 typedef struct tuple_flags {
     u_int              link_space:4;
     u_int              has_link:1;
@@ -471,7 +462,7 @@ static int follow_link(struct pcmcia_socket *s, tuple_t *tuple)
        /* Get indirect link from the MFC tuple */
        read_cis_cache(s, LINK_SPACE(tuple->Flags),
                       tuple->LinkOffset, 5, link);
-       ofs = cis_get_u32(link + 1);
+       ofs = get_unaligned_le32(link + 1);
        SPACE(tuple->Flags) = (link[0] == CISTPL_MFC_ATTR);
        /* Move to the next indirect link */
        tuple->LinkOffset += 5;
@@ -679,8 +670,8 @@ static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum)
     if (tuple->TupleDataLen < 5)
        return CS_BAD_TUPLE;
     p = (u_char *) tuple->TupleData;
-    csum->addr = tuple->CISOffset + cis_get_u16(p) - 2;
-    csum->len = cis_get_u16(p + 2);
+    csum->addr = tuple->CISOffset + get_unaligned_le16(p) - 2;
+    csum->len = get_unaligned_le16(p + 2);
     csum->sum = *(p + 4);
     return CS_SUCCESS;
 }
@@ -691,7 +682,7 @@ static int parse_longlink(tuple_t *tuple, cistpl_longlink_t *link)
 {
     if (tuple->TupleDataLen < 4)
        return CS_BAD_TUPLE;
-    link->addr = cis_get_u32(tuple->TupleData);
+    link->addr = get_unaligned_le32(tuple->TupleData);
     return CS_SUCCESS;
 }
 
@@ -710,7 +701,7 @@ static int parse_longlink_mfc(tuple_t *tuple,
        return CS_BAD_TUPLE;
     for (i = 0; i < link->nfn; i++) {
        link->fn[i].space = *p; p++;
-       link->fn[i].addr = cis_get_u32(p);
+       link->fn[i].addr = get_unaligned_le32(p);
        p += 4;
     }
     return CS_SUCCESS;
@@ -800,8 +791,8 @@ static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m)
 {
     if (tuple->TupleDataLen < 4)
        return CS_BAD_TUPLE;
-    m->manf = cis_get_u16(tuple->TupleData);
-    m->card = cis_get_u16(tuple->TupleData + 2);
+    m->manf = get_unaligned_le16(tuple->TupleData);
+    m->card = get_unaligned_le16(tuple->TupleData + 2);
     return CS_SUCCESS;
 }
 
@@ -1100,7 +1091,7 @@ static int parse_cftable_entry(tuple_t *tuple,
        break;
     case 0x20:
        entry->mem.nwin = 1;
-       entry->mem.win[0].len = cis_get_u16(p) << 8;
+       entry->mem.win[0].len = get_unaligned_le16(p) << 8;
        entry->mem.win[0].card_addr = 0;
        entry->mem.win[0].host_addr = 0;
        p += 2;
@@ -1108,8 +1099,8 @@ static int parse_cftable_entry(tuple_t *tuple,
        break;
     case 0x40:
        entry->mem.nwin = 1;
-       entry->mem.win[0].len = cis_get_u16(p) << 8;
-       entry->mem.win[0].card_addr = cis_get_u16(p + 2) << 8;
+       entry->mem.win[0].len = get_unaligned_le16(p) << 8;
+       entry->mem.win[0].card_addr = get_unaligned_le16(p + 2) << 8;
        entry->mem.win[0].host_addr = 0;
        p += 4;
        if (p > q) return CS_BAD_TUPLE;
@@ -1146,7 +1137,7 @@ static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar)
     p = (u_char *)tuple->TupleData;
     bar->attr = *p;
     p += 2;
-    bar->size = cis_get_u32(p);
+    bar->size = get_unaligned_le32(p);
     return CS_SUCCESS;
 }
 
@@ -1159,7 +1150,7 @@ static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config)
        return CS_BAD_TUPLE;
     config->last_idx = *(++p);
     p++;
-    config->base = cis_get_u32(p);
+    config->base = get_unaligned_le32(p);
     config->subtuples = tuple->TupleDataLen - 6;
     return CS_SUCCESS;
 }
@@ -1275,7 +1266,7 @@ static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2)
 
     v2->vers = p[0];
     v2->comply = p[1];
-    v2->dindex = cis_get_u16(p +2 );
+    v2->dindex = get_unaligned_le16(p +2 );
     v2->vspec8 = p[6];
     v2->vspec9 = p[7];
     v2->nhdr = p[8];
@@ -1316,8 +1307,8 @@ static int parse_format(tuple_t *tuple, cistpl_format_t *fmt)
 
     fmt->type = p[0];
     fmt->edc = p[1];
-    fmt->offset = cis_get_u32(p + 2);
-    fmt->length = cis_get_u32(p + 6);
+    fmt->offset = get_unaligned_le32(p + 2);
+    fmt->length = get_unaligned_le32(p + 6);
 
     return CS_SUCCESS;
 }
index 27523c5f4dad50a9fd9de15ff768257945716d99..5f186abca1082843a7b12e30865b3bb7c8b83f34 100644 (file)
@@ -787,7 +787,7 @@ void __init pcmcia_setup_ioctl(void) {
                major_dev = i;
 
 #ifdef CONFIG_PROC_FS
-       proc_pccard = proc_mkdir("pccard", proc_bus);
+       proc_pccard = proc_mkdir("bus/pccard", NULL);
        if (proc_pccard)
                create_proc_read_entry("drivers",0,proc_pccard,proc_read_drivers,NULL);
 #endif
@@ -798,7 +798,7 @@ void __exit pcmcia_cleanup_ioctl(void) {
 #ifdef CONFIG_PROC_FS
        if (proc_pccard) {
                remove_proc_entry("drivers", proc_pccard);
-               remove_proc_entry("pccard", proc_bus);
+               remove_proc_entry("bus/pccard", NULL);
        }
 #endif
        if (major_dev != -1)
index 2b8266c3d40f63aced5da403e66d745970d18107..3f94edab25fa7f8551d456b2d8df34e1fc0d3ed4 100644 (file)
@@ -85,6 +85,7 @@ static ssize_t isapnp_proc_bus_read(struct file *file, char __user * buf,
 }
 
 static const struct file_operations isapnp_proc_bus_file_operations = {
+       .owner  = THIS_MODULE,
        .llseek = isapnp_proc_bus_lseek,
        .read = isapnp_proc_bus_read,
 };
@@ -102,12 +103,10 @@ static int isapnp_proc_attach_device(struct pnp_dev *dev)
                        return -ENOMEM;
        }
        sprintf(name, "%02x", dev->number);
-       e = dev->procent = create_proc_entry(name, S_IFREG | S_IRUGO, de);
+       e = dev->procent = proc_create_data(name, S_IFREG | S_IRUGO, de,
+                       &isapnp_proc_bus_file_operations, dev);
        if (!e)
                return -ENOMEM;
-       e->proc_fops = &isapnp_proc_bus_file_operations;
-       e->owner = THIS_MODULE;
-       e->data = dev;
        e->size = 256;
        return 0;
 }
@@ -116,7 +115,7 @@ int __init isapnp_proc_init(void)
 {
        struct pnp_dev *dev;
 
-       isapnp_proc_bus_dir = proc_mkdir("isapnp", proc_bus);
+       isapnp_proc_bus_dir = proc_mkdir("bus/isapnp", NULL);
        protocol_for_each_dev(&isapnp_protocol, dev) {
                isapnp_proc_attach_device(dev);
        }
index bb19bc957bad9274457930b8b75b7753e62a7ac4..46d506f66259f502605e4965adc1b779afb73d80 100644 (file)
@@ -256,7 +256,7 @@ int pnpbios_interface_attach_device(struct pnp_bios_node *node)
  */
 int __init pnpbios_proc_init(void)
 {
-       proc_pnp = proc_mkdir("pnp", proc_bus);
+       proc_pnp = proc_mkdir("bus/pnp", NULL);
        if (!proc_pnp)
                return -EIO;
        proc_pnp_boot = proc_mkdir("boot", proc_pnp);
@@ -294,5 +294,5 @@ void __exit pnpbios_proc_exit(void)
        remove_proc_entry("configuration_info", proc_pnp);
        remove_proc_entry("devices", proc_pnp);
        remove_proc_entry("boot", proc_pnp);
-       remove_proc_entry("pnp", proc_bus);
+       remove_proc_entry("bus/pnp", NULL);
 }
index bdb9b7285b3d7b6b0afc744f3be084d01c1ca11b..71be36f18709e80771719103941e40c9f653f922 100644 (file)
@@ -262,7 +262,7 @@ static void ds2760_battery_work(struct work_struct *work)
                struct ds2760_device_info, monitor_work.work);
        const int interval = HZ * 60;
 
-       dev_dbg(di->dev, "%s\n", __FUNCTION__);
+       dev_dbg(di->dev, "%s\n", __func__);
 
        ds2760_battery_update_status(di);
        queue_delayed_work(di->monitor_wqueue, &di->monitor_work, interval);
@@ -275,7 +275,7 @@ static void ds2760_battery_external_power_changed(struct power_supply *psy)
 {
        struct ds2760_device_info *di = to_ds2760_device_info(psy);
 
-       dev_dbg(di->dev, "%s\n", __FUNCTION__);
+       dev_dbg(di->dev, "%s\n", __func__);
 
        cancel_delayed_work(&di->monitor_work);
        queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ/10);
index af7a231092a461052af4408f6e127901622e4f29..ab1e8289f07f4a23ca08899635e2f3e4dc02330d 100644 (file)
@@ -315,7 +315,6 @@ static int __init olpc_bat_init(void)
        if (ret)
                goto battery_failed;
 
-       olpc_register_battery_callback(&olpc_battery_trigger_uevent);
        goto success;
 
 battery_failed:
@@ -328,7 +327,6 @@ success:
 
 static void __exit olpc_bat_exit(void)
 {
-       olpc_deregister_battery_callback();
        power_supply_unregister(&olpc_bat);
        power_supply_unregister(&olpc_ac);
        platform_device_unregister(bat_pdev);
index 03d6a38464ef8ca8d27c589b35735b0452d1aa97..138dd76ee347b005aaf21b01f3b68a0869731045 100644 (file)
@@ -39,7 +39,7 @@ static void power_supply_changed_work(struct work_struct *work)
        struct power_supply *psy = container_of(work, struct power_supply,
                                                changed_work);
 
-       dev_dbg(psy->dev, "%s\n", __FUNCTION__);
+       dev_dbg(psy->dev, "%s\n", __func__);
 
        class_for_each_device(power_supply_class, psy,
                              __power_supply_changed_work);
@@ -51,7 +51,7 @@ static void power_supply_changed_work(struct work_struct *work)
 
 void power_supply_changed(struct power_supply *psy)
 {
-       dev_dbg(psy->dev, "%s\n", __FUNCTION__);
+       dev_dbg(psy->dev, "%s\n", __func__);
 
        schedule_work(&psy->changed_work);
 }
@@ -82,7 +82,7 @@ int power_supply_am_i_supplied(struct power_supply *psy)
        error = class_for_each_device(power_supply_class, psy,
                                      __power_supply_am_i_supplied);
 
-       dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, error);
+       dev_dbg(psy->dev, "%s %d\n", __func__, error);
 
        return error;
 }
index fa3034f85c382d4a3dc3b5bdb6ed36469c46042a..2dece40c544f2098dae9b94ae110f31c8f50be31 100644 (file)
@@ -24,7 +24,7 @@ static void power_supply_update_bat_leds(struct power_supply *psy)
        if (psy->get_property(psy, POWER_SUPPLY_PROP_STATUS, &status))
                return;
 
-       dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, status.intval);
+       dev_dbg(psy->dev, "%s %d\n", __func__, status.intval);
 
        switch (status.intval) {
        case POWER_SUPPLY_STATUS_FULL:
@@ -101,7 +101,7 @@ static void power_supply_update_gen_leds(struct power_supply *psy)
        if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &online))
                return;
 
-       dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, online.intval);
+       dev_dbg(psy->dev, "%s %d\n", __func__, online.intval);
 
        if (online.intval)
                led_trigger_event(psy->online_trig, LED_FULL);
index 4f28045d9ef201706e0aff6f7e330f564c758ab5..8624f55d05608cabe99e6f91a9e18220be699a13 100644 (file)
@@ -419,7 +419,7 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        rtc->rtc_dev = rtc_device_register(pdev->name, &pdev->dev, &bfin_rtc_ops, THIS_MODULE);
-       if (unlikely(IS_ERR(rtc))) {
+       if (IS_ERR(rtc)) {
                ret = PTR_ERR(rtc->rtc_dev);
                goto err;
        }
index f389a28720d2da4302c05a1ef56e2fc5530272a7..bbf97e65202a24327b57beafbba98d6daca738a2 100644 (file)
@@ -99,45 +99,38 @@ struct ds1307 {
 };
 
 struct chip_desc {
-       char                    name[9];
        unsigned                nvram56:1;
        unsigned                alarm:1;
-       enum ds_type            type;
 };
 
-static const struct chip_desc chips[] = { {
-       .name           = "ds1307",
-       .type           = ds_1307,
+static const struct chip_desc chips[] = {
+[ds_1307] = {
        .nvram56        = 1,
-}, {
-       .name           = "ds1337",
-       .type           = ds_1337,
+},
+[ds_1337] = {
        .alarm          = 1,
-}, {
-       .name           = "ds1338",
-       .type           = ds_1338,
+},
+[ds_1338] = {
        .nvram56        = 1,
-}, {
-       .name           = "ds1339",
-       .type           = ds_1339,
+},
+[ds_1339] = {
        .alarm          = 1,
-}, {
-       .name           = "ds1340",
-       .type           = ds_1340,
-}, {
-       .name           = "m41t00",
-       .type           = m41t00,
+},
+[ds_1340] = {
+},
+[m41t00] = {
 }, };
 
-static inline const struct chip_desc *find_chip(const char *s)
-{
-       unsigned i;
-
-       for (i = 0; i < ARRAY_SIZE(chips); i++)
-               if (strnicmp(s, chips[i].name, sizeof chips[i].name) == 0)
-                       return &chips[i];
-       return NULL;
-}
+static const struct i2c_device_id ds1307_id[] = {
+       { "ds1307", ds_1307 },
+       { "ds1337", ds_1337 },
+       { "ds1338", ds_1338 },
+       { "ds1339", ds_1339 },
+       { "ds1340", ds_1340 },
+       { "m41t00", m41t00 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, ds1307_id);
 
 static int ds1307_get_time(struct device *dev, struct rtc_time *t)
 {
@@ -326,21 +319,15 @@ static struct bin_attribute nvram = {
 
 static struct i2c_driver ds1307_driver;
 
-static int __devinit ds1307_probe(struct i2c_client *client)
+static int __devinit ds1307_probe(struct i2c_client *client,
+                                 const struct i2c_device_id *id)
 {
        struct ds1307           *ds1307;
        int                     err = -ENODEV;
        int                     tmp;
-       const struct chip_desc  *chip;
+       const struct chip_desc  *chip = &chips[id->driver_data];
        struct i2c_adapter      *adapter = to_i2c_adapter(client->dev.parent);
 
-       chip = find_chip(client->name);
-       if (!chip) {
-               dev_err(&client->dev, "unknown chip type '%s'\n",
-                               client->name);
-               return -ENODEV;
-       }
-
        if (!i2c_check_functionality(adapter,
                        I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
                return -EIO;
@@ -361,7 +348,7 @@ static int __devinit ds1307_probe(struct i2c_client *client)
        ds1307->msg[1].len = sizeof(ds1307->regs);
        ds1307->msg[1].buf = ds1307->regs;
 
-       ds1307->type = chip->type;
+       ds1307->type = id->driver_data;
 
        switch (ds1307->type) {
        case ds_1337:
@@ -550,6 +537,7 @@ static struct i2c_driver ds1307_driver = {
        },
        .probe          = ds1307_probe,
        .remove         = __devexit_p(ds1307_remove),
+       .id_table       = ds1307_id,
 };
 
 static int __init ds1307_init(void)
index 45bda186befc2e1bfaf8bc3ff71f7cf02eec1d6a..fa2d2f8b3f4d071bca31834a46c1ac58c1367fe5 100644 (file)
 #define DS1374_REG_SR_AF       0x01 /* Alarm Flag */
 #define DS1374_REG_TCR         0x09 /* Trickle Charge */
 
+static const struct i2c_device_id ds1374_id[] = {
+       { "rtc-ds1374", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, ds1374_id);
+
 struct ds1374 {
        struct i2c_client *client;
        struct rtc_device *rtc;
@@ -355,7 +361,8 @@ static const struct rtc_class_ops ds1374_rtc_ops = {
        .ioctl = ds1374_ioctl,
 };
 
-static int ds1374_probe(struct i2c_client *client)
+static int ds1374_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
 {
        struct ds1374 *ds1374;
        int ret;
@@ -429,6 +436,7 @@ static struct i2c_driver ds1374_driver = {
        },
        .probe = ds1374_probe,
        .remove = __devexit_p(ds1374_remove),
+       .id_table = ds1374_id,
 };
 
 static int __init ds1374_init(void)
index fb15e3fb4ce279df7df4cba4fc387b6620d6427c..fbb90b1e40981f6fadfd4542e468ad35a3d70f4d 100644 (file)
@@ -490,7 +490,7 @@ isl1208_sysfs_unregister(struct device *dev)
 }
 
 static int
-isl1208_probe(struct i2c_client *client)
+isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
        int rc = 0;
        struct rtc_device *rtc;
@@ -545,12 +545,19 @@ isl1208_remove(struct i2c_client *client)
        return 0;
 }
 
+static const struct i2c_device_id isl1208_id[] = {
+       { "isl1208", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, isl1208_id);
+
 static struct i2c_driver isl1208_driver = {
        .driver = {
                   .name = "rtc-isl1208",
                   },
        .probe = isl1208_probe,
        .remove = isl1208_remove,
+       .id_table = isl1208_id,
 };
 
 static int __init
index 1cb33cac12377095fc075e07e4341306dcda4bcc..316bfaa80872195badfeda9ec87de81265d77d96 100644 (file)
 
 #define DRV_VERSION "0.05"
 
-struct m41t80_chip_info {
-       const char *name;
-       u8 features;
-};
-
-static const struct m41t80_chip_info m41t80_chip_info_tbl[] = {
-       {
-               .name           = "m41t80",
-               .features       = 0,
-       },
-       {
-               .name           = "m41t81",
-               .features       = M41T80_FEATURE_HT,
-       },
-       {
-               .name           = "m41t81s",
-               .features       = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
-       },
-       {
-               .name           = "m41t82",
-               .features       = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
-       },
-       {
-               .name           = "m41t83",
-               .features       = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
-       },
-       {
-               .name           = "m41st84",
-               .features       = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
-       },
-       {
-               .name           = "m41st85",
-               .features       = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
-       },
-       {
-               .name           = "m41st87",
-               .features       = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
-       },
+static const struct i2c_device_id m41t80_id[] = {
+       { "m41t80", 0 },
+       { "m41t81", M41T80_FEATURE_HT },
+       { "m41t81s", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
+       { "m41t82", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
+       { "m41t83", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
+       { "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
+       { "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
+       { "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
+       { }
 };
+MODULE_DEVICE_TABLE(i2c, m41t80_id);
 
 struct m41t80_data {
-       const struct m41t80_chip_info *chip;
+       u8 features;
        struct rtc_device *rtc;
 };
 
@@ -208,7 +181,7 @@ static int m41t80_rtc_proc(struct device *dev, struct seq_file *seq)
        struct m41t80_data *clientdata = i2c_get_clientdata(client);
        u8 reg;
 
-       if (clientdata->chip->features & M41T80_FEATURE_BL) {
+       if (clientdata->features & M41T80_FEATURE_BL) {
                reg = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
                seq_printf(seq, "battery\t\t: %s\n",
                           (reg & M41T80_FLAGS_BATT_LOW) ? "exhausted" : "ok");
@@ -756,12 +729,12 @@ static struct notifier_block wdt_notifier = {
  *
  *****************************************************************************
  */
-static int m41t80_probe(struct i2c_client *client)
+static int m41t80_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
 {
-       int i, rc = 0;
+       int rc = 0;
        struct rtc_device *rtc = NULL;
        struct rtc_time tm;
-       const struct m41t80_chip_info *chip;
        struct m41t80_data *clientdata = NULL;
 
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C
@@ -773,19 +746,6 @@ static int m41t80_probe(struct i2c_client *client)
        dev_info(&client->dev,
                 "chip found, driver version " DRV_VERSION "\n");
 
-       chip = NULL;
-       for (i = 0; i < ARRAY_SIZE(m41t80_chip_info_tbl); i++) {
-               if (!strcmp(m41t80_chip_info_tbl[i].name, client->name)) {
-                       chip = &m41t80_chip_info_tbl[i];
-                       break;
-               }
-       }
-       if (!chip) {
-               dev_err(&client->dev, "%s is not supported\n", client->name);
-               rc = -ENODEV;
-               goto exit;
-       }
-
        clientdata = kzalloc(sizeof(*clientdata), GFP_KERNEL);
        if (!clientdata) {
                rc = -ENOMEM;
@@ -801,7 +761,7 @@ static int m41t80_probe(struct i2c_client *client)
        }
 
        clientdata->rtc = rtc;
-       clientdata->chip = chip;
+       clientdata->features = id->driver_data;
        i2c_set_clientdata(client, clientdata);
 
        /* Make sure HT (Halt Update) bit is cleared */
@@ -810,7 +770,7 @@ static int m41t80_probe(struct i2c_client *client)
                goto ht_err;
 
        if (rc & M41T80_ALHOUR_HT) {
-               if (chip->features & M41T80_FEATURE_HT) {
+               if (clientdata->features & M41T80_FEATURE_HT) {
                        m41t80_get_datetime(client, &tm);
                        dev_info(&client->dev, "HT bit was set!\n");
                        dev_info(&client->dev,
@@ -842,7 +802,7 @@ static int m41t80_probe(struct i2c_client *client)
                goto exit;
 
 #ifdef CONFIG_RTC_DRV_M41T80_WDT
-       if (chip->features & M41T80_FEATURE_HT) {
+       if (clientdata->features & M41T80_FEATURE_HT) {
                rc = misc_register(&wdt_dev);
                if (rc)
                        goto exit;
@@ -878,7 +838,7 @@ static int m41t80_remove(struct i2c_client *client)
        struct rtc_device *rtc = clientdata->rtc;
 
 #ifdef CONFIG_RTC_DRV_M41T80_WDT
-       if (clientdata->chip->features & M41T80_FEATURE_HT) {
+       if (clientdata->features & M41T80_FEATURE_HT) {
                misc_deregister(&wdt_dev);
                unregister_reboot_notifier(&wdt_notifier);
        }
@@ -896,6 +856,7 @@ static struct i2c_driver m41t80_driver = {
        },
        .probe = m41t80_probe,
        .remove = m41t80_remove,
+       .id_table = m41t80_id,
 };
 
 static int __init m41t80_rtc_init(void)
index a41681d26eba80ae58df5b0090ae603fbab519fe..0fc4c363078003e6d189f39a8b3f6f5a4ddd790a 100644 (file)
@@ -246,7 +246,8 @@ static const struct rtc_class_ops pcf8563_rtc_ops = {
        .set_time       = pcf8563_rtc_set_time,
 };
 
-static int pcf8563_probe(struct i2c_client *client)
+static int pcf8563_probe(struct i2c_client *client,
+                               const struct i2c_device_id *id)
 {
        struct pcf8563 *pcf8563;
 
@@ -299,12 +300,19 @@ static int pcf8563_remove(struct i2c_client *client)
        return 0;
 }
 
+static const struct i2c_device_id pcf8563_id[] = {
+       { "pcf8563", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, pcf8563_id);
+
 static struct i2c_driver pcf8563_driver = {
        .driver         = {
                .name   = "rtc-pcf8563",
        },
        .probe          = pcf8563_probe,
        .remove         = pcf8563_remove,
+       .id_table       = pcf8563_id,
 };
 
 static int __init pcf8563_init(void)
index 8d300e6d0d9e92eedc96a87cc2055cc4062d7180..0c6257a034ff07b3dc85e9ce1db3847571c97fc4 100644 (file)
@@ -108,12 +108,10 @@ void rtc_proc_add_device(struct rtc_device *rtc)
        if (rtc->id == 0) {
                struct proc_dir_entry *ent;
 
-               ent = create_proc_entry("driver/rtc", 0, NULL);
-               if (ent) {
-                       ent->proc_fops = &rtc_proc_fops;
+               ent = proc_create_data("driver/rtc", 0, NULL,
+                                      &rtc_proc_fops, rtc);
+               if (ent)
                        ent->owner = rtc->owner;
-                       ent->data = rtc;
-               }
        }
 }
 
index 7e63074708ebffa060c1f2b5b405ac37790323b5..56caf6b2c3e5d2fceface127d7dc197a839e0dac 100644 (file)
@@ -69,6 +69,15 @@ enum rtc_type {
        rtc_rv5c387a,
 };
 
+static const struct i2c_device_id rs5c372_id[] = {
+       { "rs5c372a", rtc_rs5c372a },
+       { "rs5c372b", rtc_rs5c372b },
+       { "rv5c386", rtc_rv5c386 },
+       { "rv5c387a", rtc_rv5c387a },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, rs5c372_id);
+
 /* REVISIT:  this assumes that:
  *  - we're in the 21st century, so it's safe to ignore the century
  *    bit for rv5c38[67] (REG_MONTH bit 7);
@@ -494,7 +503,8 @@ static void rs5c_sysfs_unregister(struct device *dev)
 
 static struct i2c_driver rs5c372_driver;
 
-static int rs5c372_probe(struct i2c_client *client)
+static int rs5c372_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
 {
        int err = 0;
        struct rs5c372 *rs5c372;
@@ -514,6 +524,7 @@ static int rs5c372_probe(struct i2c_client *client)
 
        rs5c372->client = client;
        i2c_set_clientdata(client, rs5c372);
+       rs5c372->type = id->driver_data;
 
        /* we read registers 0x0f then 0x00-0x0f; skip the first one */
        rs5c372->regs = &rs5c372->buf[1];
@@ -522,19 +533,6 @@ static int rs5c372_probe(struct i2c_client *client)
        if (err < 0)
                goto exit_kfree;
 
-       if (strcmp(client->name, "rs5c372a") == 0)
-               rs5c372->type = rtc_rs5c372a;
-       else if (strcmp(client->name, "rs5c372b") == 0)
-               rs5c372->type = rtc_rs5c372b;
-       else if (strcmp(client->name, "rv5c386") == 0)
-               rs5c372->type = rtc_rv5c386;
-       else if (strcmp(client->name, "rv5c387a") == 0)
-               rs5c372->type = rtc_rv5c387a;
-       else {
-               rs5c372->type = rtc_rs5c372b;
-               dev_warn(&client->dev, "assuming rs5c372b\n");
-       }
-
        /* clock may be set for am/pm or 24 hr time */
        switch (rs5c372->type) {
        case rtc_rs5c372a:
@@ -651,6 +649,7 @@ static struct i2c_driver rs5c372_driver = {
        },
        .probe          = rs5c372_probe,
        .remove         = rs5c372_remove,
+       .id_table       = rs5c372_id,
 };
 
 static __init int rs5c372_init(void)
index e8abc90c32c5fe0e82938ad7d4b711807a8c7779..29f47bacfc77b5503086473f858fb1cc6124f33e 100644 (file)
 #define S35390A_FLAG_RESET     0x80
 #define S35390A_FLAG_TEST      0x01
 
+static const struct i2c_device_id s35390a_id[] = {
+       { "s35390a", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, s35390a_id);
+
 struct s35390a {
        struct i2c_client *client[8];
        struct rtc_device *rtc;
@@ -195,7 +201,8 @@ static const struct rtc_class_ops s35390a_rtc_ops = {
 
 static struct i2c_driver s35390a_driver;
 
-static int s35390a_probe(struct i2c_client *client)
+static int s35390a_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
 {
        int err;
        unsigned int i;
@@ -296,6 +303,7 @@ static struct i2c_driver s35390a_driver = {
        },
        .probe          = s35390a_probe,
        .remove         = s35390a_remove,
+       .id_table       = s35390a_id,
 };
 
 static int __init s35390a_rtc_init(void)
index 095282f635236b106b9eb3b51b7a354f39b813ac..eaf55945f21bbf860318a082b24463caa8648ebc 100644 (file)
@@ -494,7 +494,8 @@ static void x1205_sysfs_unregister(struct device *dev)
 }
 
 
-static int x1205_probe(struct i2c_client *client)
+static int x1205_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
 {
        int err = 0;
        unsigned char sr;
@@ -552,12 +553,19 @@ static int x1205_remove(struct i2c_client *client)
        return 0;
 }
 
+static const struct i2c_device_id x1205_id[] = {
+       { "x1205", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, x1205_id);
+
 static struct i2c_driver x1205_driver = {
        .driver         = {
                .name   = "rtc-x1205",
        },
        .probe          = x1205_probe,
        .remove         = x1205_remove,
+       .id_table       = x1205_id,
 };
 
 static int __init x1205_init(void)
index 556063e8f7a91d1163450cc63d1cd9128e6a77b4..03c0e40a92ff9fafc20694ee0127822d03a4db4f 100644 (file)
@@ -157,6 +157,7 @@ static int dasd_devices_open(struct inode *inode, struct file *file)
 }
 
 static const struct file_operations dasd_devices_file_ops = {
+       .owner          = THIS_MODULE,
        .open           = dasd_devices_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -311,17 +312,16 @@ out_error:
 int
 dasd_proc_init(void)
 {
-       dasd_proc_root_entry = proc_mkdir("dasd", &proc_root);
+       dasd_proc_root_entry = proc_mkdir("dasd", NULL);
        if (!dasd_proc_root_entry)
                goto out_nodasd;
        dasd_proc_root_entry->owner = THIS_MODULE;
-       dasd_devices_entry = create_proc_entry("devices",
-                                              S_IFREG | S_IRUGO | S_IWUSR,
-                                              dasd_proc_root_entry);
+       dasd_devices_entry = proc_create("devices",
+                                        S_IFREG | S_IRUGO | S_IWUSR,
+                                        dasd_proc_root_entry,
+                                        &dasd_devices_file_ops);
        if (!dasd_devices_entry)
                goto out_nodevices;
-       dasd_devices_entry->proc_fops = &dasd_devices_file_ops;
-       dasd_devices_entry->owner = THIS_MODULE;
        dasd_statistics_entry = create_proc_entry("statistics",
                                                  S_IFREG | S_IRUGO | S_IWUSR,
                                                  dasd_proc_root_entry);
@@ -335,7 +335,7 @@ dasd_proc_init(void)
  out_nostatistics:
        remove_proc_entry("devices", dasd_proc_root_entry);
  out_nodevices:
-       remove_proc_entry("dasd", &proc_root);
+       remove_proc_entry("dasd", NULL);
  out_nodasd:
        return -ENOENT;
 }
@@ -345,5 +345,5 @@ dasd_proc_exit(void)
 {
        remove_proc_entry("devices", dasd_proc_root_entry);
        remove_proc_entry("statistics", dasd_proc_root_entry);
-       remove_proc_entry("dasd", &proc_root);
+       remove_proc_entry("dasd", NULL);
 }
index 0e1f35c9ed9d4e0be6dc928d0d3bf69182799149..3e5653c92f4b5e5b6d1c5b1edd14b5f6eaa23af6 100644 (file)
@@ -982,15 +982,16 @@ tty3215_write(struct tty_struct * tty,
 /*
  * Put character routine for 3215 ttys
  */
-static void
+static int
 tty3215_put_char(struct tty_struct *tty, unsigned char ch)
 {
        struct raw3215_info *raw;
 
        if (!tty)
-               return;
+               return 0;
        raw = (struct raw3215_info *) tty->driver_data;
        raw3215_putchar(raw, ch);
+       return 1;
 }
 
 static void
index e3b3d390b4a3b2294f23428c6e5b70b688298f23..40b11521cd20246ee308a34c92909f7c849058e9 100644 (file)
@@ -412,14 +412,14 @@ sclp_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
  * - including previous characters from sclp_tty_put_char() and strings from
  * sclp_write() without final '\n' - will be written.
  */
-static void
+static int
 sclp_tty_put_char(struct tty_struct *tty, unsigned char ch)
 {
        sclp_tty_chars[sclp_tty_chars_count++] = ch;
        if (ch == '\n' || sclp_tty_chars_count >= SCLP_TTY_BUF_SIZE) {
                sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count);
                sclp_tty_chars_count = 0;
-       }
+       } return 1;
 }
 
 /*
index ed507594e62ba0adf12fde30a1ecd23a91509180..35707c04e613fd7708acea79ccbbc4119d3d4851 100644 (file)
@@ -524,11 +524,15 @@ sclp_vt220_close(struct tty_struct *tty, struct file *filp)
  * NOTE: include/linux/tty_driver.h specifies that a character should be
  * ignored if there is no room in the queue. This driver implements a different
  * semantic in that it will block when there is no more room left.
+ *
+ * FIXME: putchar can currently be called from BH and other non blocking
+ * handlers so  this semantic isn't a good idea.
  */
-static void
+static int
 sclp_vt220_put_char(struct tty_struct *tty, unsigned char ch)
 {
        __sclp_vt220_write(&ch, 1, 0, 0, 1);
+       return 1;
 }
 
 /*
index c9b96d51b28f25d36ab9fa85fbc34e60648fc3e0..e7c888c14e71f847b6ba8aa05e2797c700a2ca6a 100644 (file)
@@ -111,6 +111,7 @@ static int tape_proc_open(struct inode *inode, struct file *file)
 
 static const struct file_operations tape_proc_ops =
 {
+       .owner          = THIS_MODULE,
        .open           = tape_proc_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -124,14 +125,12 @@ void
 tape_proc_init(void)
 {
        tape_proc_devices =
-               create_proc_entry ("tapedevices", S_IFREG | S_IRUGO | S_IWUSR,
-                                  &proc_root);
+               proc_create("tapedevices", S_IFREG | S_IRUGO | S_IWUSR, NULL,
+                           &tape_proc_ops);
        if (tape_proc_devices == NULL) {
                PRINT_WARN("tape: Cannot register procfs entry tapedevices\n");
                return;
        }
-       tape_proc_devices->proc_fops = &tape_proc_ops;
-       tape_proc_devices->owner = THIS_MODULE;
 }
 
 /*
@@ -141,5 +140,5 @@ void
 tape_proc_cleanup(void)
 {
        if (tape_proc_devices != NULL)
-               remove_proc_entry ("tapedevices", &proc_root);
+               remove_proc_entry ("tapedevices", NULL);
 }
index 70b1980a08b66380c075355d81101c90a784032f..c1f2adefad410287fe170ae77a8baa47a8611187 100644 (file)
@@ -965,7 +965,7 @@ tty3270_write_room(struct tty_struct *tty)
  * Insert character into the screen at the current position with the
  * current color and highlight. This function does NOT do cursor movement.
  */
-static void
+static int
 tty3270_put_character(struct tty3270 *tp, char ch)
 {
        struct tty3270_line *line;
@@ -986,6 +986,7 @@ tty3270_put_character(struct tty3270 *tp, char ch)
        cell->character = tp->view.ascebc[(unsigned int) ch];
        cell->highlight = tp->highlight;
        cell->f_color = tp->f_color;
+       return 1;
 }
 
 /*
index e8597ec92247b2eb9127f32448b24c47b12a50e1..40ef948fcb3a5e9b2441bacb6a78fd65f9a693cf 100644 (file)
@@ -374,13 +374,10 @@ cio_ignore_proc_init (void)
 {
        struct proc_dir_entry *entry;
 
-       entry = create_proc_entry ("cio_ignore", S_IFREG | S_IRUGO | S_IWUSR,
-                                  &proc_root);
+       entry = proc_create("cio_ignore", S_IFREG | S_IRUGO | S_IWUSR, NULL,
+                           &cio_ignore_proc_fops);
        if (!entry)
                return -ENOENT;
-
-       entry->proc_fops = &cio_ignore_proc_fops;
-
        return 0;
 }
 
index 10aa1e780801f42db88b0cf2006ad2e194744763..43876e287370ddce9e75e89e5e0787216da6a461 100644 (file)
@@ -3632,7 +3632,7 @@ qdio_add_procfs_entry(void)
 {
         proc_perf_file_registration=0;
        qdio_perf_proc_file=create_proc_entry(QDIO_PERF,
-                                             S_IFREG|0444,&proc_root);
+                                             S_IFREG|0444,NULL);
        if (qdio_perf_proc_file) {
                qdio_perf_proc_file->read_proc=&qdio_perf_procfile_read;
        } else proc_perf_file_registration=-1;
@@ -3647,7 +3647,7 @@ static void
 qdio_remove_procfs_entry(void)
 {
         if (!proc_perf_file_registration) /* means if it went ok earlier */
-               remove_proc_entry(QDIO_PERF,&proc_root);
+               remove_proc_entry(QDIO_PERF,NULL);
 }
 
 /**
index a4e758143665aa2427aa97ecf6f86dcfbb20d4c2..235703414370b8aac9329e783319dc92f49b7546 100644 (file)
@@ -637,7 +637,7 @@ static int wd_inittimer(int whichdog)
                        break;
                default:
                        printk("%s: %s: invalid watchdog id: %i\n",
-                               WD_OBPNAME, __FUNCTION__, whichdog);
+                               WD_OBPNAME, __func__, whichdog);
                        return(1);
        }
        if(0 != misc_register(whichmisc))
index 44d2ef906ac732aa7b0a4c92467602ad128ab9e6..383f32c1d347c33b9ed63bf9e479b8ae237a94e7 100644 (file)
@@ -393,13 +393,13 @@ static int __init ts102_uctrl_init(void)
        err = request_irq(driver->irq, uctrl_interrupt, 0, "uctrl", driver);
        if (err) {
                printk("%s: unable to register irq %d\n",
-                      __FUNCTION__, driver->irq);
+                      __func__, driver->irq);
                return err;
        }
 
        if (misc_register(&uctrl_dev)) {
                printk("%s: unable to get misc minor %d\n",
-                      __FUNCTION__, uctrl_dev.minor);
+                      __func__, uctrl_dev.minor);
                free_irq(driver->irq, driver);
                return -ENODEV;
        }
index b135a1ed4b2cff191c1235106131ba4ca9f44229..18551aaf5e094e07612ddf028df0dc7f2a05d344 100644 (file)
@@ -4996,7 +4996,7 @@ static int __init megaraid_init(void)
                max_mbox_busy_wait = MBOX_BUSY_WAIT;
 
 #ifdef CONFIG_PROC_FS
-       mega_proc_dir_entry = proc_mkdir("megaraid", &proc_root);
+       mega_proc_dir_entry = proc_mkdir("megaraid", NULL);
        if (!mega_proc_dir_entry) {
                printk(KERN_WARNING
                                "megaraid: failed to create megaraid root\n");
@@ -5005,7 +5005,7 @@ static int __init megaraid_init(void)
        error = pci_register_driver(&megaraid_pci_driver);
        if (error) {
 #ifdef CONFIG_PROC_FS
-               remove_proc_entry("megaraid", &proc_root);
+               remove_proc_entry("megaraid", NULL);
 #endif
                return error;
        }
@@ -5035,7 +5035,7 @@ static void __exit megaraid_exit(void)
        pci_unregister_driver(&megaraid_pci_driver);
 
 #ifdef CONFIG_PROC_FS
-       remove_proc_entry("megaraid", &proc_root);
+       remove_proc_entry("megaraid", NULL);
 #endif
 }
 
index 07103c399fe0c2e7ce840fcdcb7d995bd277ca73..f6600bfb5bde71ffc244260ec6aa1aec4cf59469 100644 (file)
@@ -1773,7 +1773,7 @@ static int scsi_debug_slave_alloc(struct scsi_device *sdp)
        if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
                printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n",
                       sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
-       set_bit(QUEUE_FLAG_BIDI, &sdp->request_queue->queue_flags);
+       queue_flag_set_unlocked(QUEUE_FLAG_BIDI, sdp->request_queue);
        return 0;
 }
 
index b8de041bc0ae8a2e894aeb723e67b98b9afe09a1..a235802f298150e648eb5bdf3f054dae4b1721c8 100644 (file)
@@ -449,37 +449,40 @@ int scsi_get_device_flags(struct scsi_device *sdev,
 }
 
 #ifdef CONFIG_SCSI_PROC_FS
-/* 
- * proc_scsi_dev_info_read: dump the scsi_dev_info_list via
- * /proc/scsi/device_info
- */
-static int proc_scsi_devinfo_read(char *buffer, char **start,
-                                 off_t offset, int length)
+static int devinfo_seq_show(struct seq_file *m, void *v)
 {
-       struct scsi_dev_info_list *devinfo;
-       int size, len = 0;
-       off_t begin = 0;
-       off_t pos = 0;
+       struct scsi_dev_info_list *devinfo =
+               list_entry(v, struct scsi_dev_info_list, dev_info_list);
 
-       list_for_each_entry(devinfo, &scsi_dev_info_list, dev_info_list) {
-               size = sprintf(buffer + len, "'%.8s' '%.16s' 0x%x\n",
+       seq_printf(m, "'%.8s' '%.16s' 0x%x\n",
                        devinfo->vendor, devinfo->model, devinfo->flags);
-               len += size;
-               pos = begin + len;
-               if (pos < offset) {
-                       len = 0;
-                       begin = pos;
-               }
-               if (pos > offset + length)
-                       goto stop_output;
-       }
+       return 0;
+}
+
+static void * devinfo_seq_start(struct seq_file *m, loff_t *pos)
+{
+       return seq_list_start(&scsi_dev_info_list, *pos);
+}
 
-stop_output:
-       *start = buffer + (offset - begin);     /* Start of wanted data */
-       len -= (offset - begin);        /* Start slop */
-       if (len > length)
-               len = length;   /* Ending slop */
-       return (len);
+static void * devinfo_seq_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       return seq_list_next(v, &scsi_dev_info_list, pos);
+}
+
+static void devinfo_seq_stop(struct seq_file *m, void *v)
+{
+}
+
+static const struct seq_operations scsi_devinfo_seq_ops = {
+       .start  = devinfo_seq_start,
+       .next   = devinfo_seq_next,
+       .stop   = devinfo_seq_stop,
+       .show   = devinfo_seq_show,
+};
+
+static int proc_scsi_devinfo_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &scsi_devinfo_seq_ops);
 }
 
 /* 
@@ -489,11 +492,12 @@ stop_output:
  * integer value of flag to the scsi device info list.
  * To use, echo "vendor:model:flag" > /proc/scsi/device_info
  */
-static int proc_scsi_devinfo_write(struct file *file, const char __user *buf,
-                                  unsigned long length, void *data)
+static ssize_t proc_scsi_devinfo_write(struct file *file,
+                                      const char __user *buf,
+                                      size_t length, loff_t *ppos)
 {
        char *buffer;
-       int err = length;
+       ssize_t err = length;
 
        if (!buf || length>PAGE_SIZE)
                return -EINVAL;
@@ -517,6 +521,15 @@ out:
        free_page((unsigned long)buffer);
        return err;
 }
+
+static const struct file_operations scsi_devinfo_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = proc_scsi_devinfo_open,
+       .read           = seq_read,
+       .write          = proc_scsi_devinfo_write,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
 #endif /* CONFIG_SCSI_PROC_FS */
 
 module_param_string(dev_flags, scsi_dev_flags, sizeof(scsi_dev_flags), 0);
@@ -577,15 +590,13 @@ int __init scsi_init_devinfo(void)
        }
 
 #ifdef CONFIG_SCSI_PROC_FS
-       p = create_proc_entry("scsi/device_info", 0, NULL);
+       p = proc_create("scsi/device_info", 0, NULL, &scsi_devinfo_proc_fops);
        if (!p) {
                error = -ENOMEM;
                goto out;
        }
 
        p->owner = THIS_MODULE;
-       p->get_info = proc_scsi_devinfo_read;
-       p->write_proc = proc_scsi_devinfo_write;
 #endif /* CONFIG_SCSI_PROC_FS */
 
  out:
index 221f31e36d26e5c4f7bfe88b7abde0b2996c982e..1eaba6cd80f411735b390a984a3f61837e377432 100644 (file)
@@ -1771,6 +1771,7 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
        unsigned long flags;
        int rtn;
 
+       blk_rq_init(NULL, &req);
        scmd->request = &req;
        memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout));
 
index 67f412bb4974b91783009fb3404c4a589bb6f6c8..d545ad1cf47a7f94c70369da8c1b6fb4dab0fe9d 100644 (file)
@@ -536,6 +536,9 @@ static void scsi_run_queue(struct request_queue *q)
               !shost->host_blocked && !shost->host_self_blocked &&
                !((shost->can_queue > 0) &&
                  (shost->host_busy >= shost->can_queue))) {
+
+               int flagset;
+
                /*
                 * As long as shost is accepting commands and we have
                 * starved queues, call blk_run_queue. scsi_request_fn
@@ -549,19 +552,20 @@ static void scsi_run_queue(struct request_queue *q)
                sdev = list_entry(shost->starved_list.next,
                                          struct scsi_device, starved_entry);
                list_del_init(&sdev->starved_entry);
-               spin_unlock_irqrestore(shost->host_lock, flags);
-
+               spin_unlock(shost->host_lock);
+
+               spin_lock(sdev->request_queue->queue_lock);
+               flagset = test_bit(QUEUE_FLAG_REENTER, &q->queue_flags) &&
+                               !test_bit(QUEUE_FLAG_REENTER,
+                                       &sdev->request_queue->queue_flags);
+               if (flagset)
+                       queue_flag_set(QUEUE_FLAG_REENTER, sdev->request_queue);
+               __blk_run_queue(sdev->request_queue);
+               if (flagset)
+                       queue_flag_clear(QUEUE_FLAG_REENTER, sdev->request_queue);
+               spin_unlock(sdev->request_queue->queue_lock);
 
-               if (test_bit(QUEUE_FLAG_REENTER, &q->queue_flags) &&
-                   !test_and_set_bit(QUEUE_FLAG_REENTER,
-                                     &sdev->request_queue->queue_flags)) {
-                       blk_run_queue(sdev->request_queue);
-                       clear_bit(QUEUE_FLAG_REENTER,
-                                 &sdev->request_queue->queue_flags);
-               } else
-                       blk_run_queue(sdev->request_queue);
-
-               spin_lock_irqsave(shost->host_lock, flags);
+               spin_lock(shost->host_lock);
                if (unlikely(!list_empty(&sdev->starved_entry)))
                        /*
                         * sdev lost a race, and was put back on the
@@ -1585,8 +1589,9 @@ struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost,
 
        blk_queue_max_segment_size(q, dma_get_max_seg_size(dev));
 
+       /* New queue, no concurrency on queue_flags */
        if (!shost->use_clustering)
-               clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
+               queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q);
 
        /*
         * set a reasonable default alignment on word boundaries: the
index 3a1c99d5c775482efedcf2a550218c23e3cf139d..e4a0d2f9b35752a47c2e84b7e99dafa67fce04f7 100644 (file)
@@ -413,6 +413,7 @@ static int proc_scsi_open(struct inode *inode, struct file *file)
 }
 
 static const struct file_operations proc_scsi_operations = {
+       .owner          = THIS_MODULE,
        .open           = proc_scsi_open,
        .read           = seq_read,
        .write          = proc_scsi_write,
@@ -431,10 +432,9 @@ int __init scsi_init_procfs(void)
        if (!proc_scsi)
                goto err1;
 
-       pde = create_proc_entry("scsi/scsi", 0, NULL);
+       pde = proc_create("scsi/scsi", 0, NULL, &proc_scsi_operations);
        if (!pde)
                goto err2;
-       pde->proc_fops = &proc_scsi_operations;
 
        return 0;
 
index fcd7455ffc39acf226233c10c3a45c1ee76537e0..a00eee6f7be9fc85d85f3eb4f33516aa22d8689b 100644 (file)
@@ -1828,7 +1828,7 @@ void scsi_scan_host(struct Scsi_Host *shost)
        }
 
        p = kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no);
-       if (unlikely(IS_ERR(p)))
+       if (IS_ERR(p))
                do_scan_async(data);
 }
 EXPORT_SYMBOL(scsi_scan_host);
index 7899e3dda9bfd7ccf357f98ed299c77af8b18013..f4461d35ffb9157d6cc3e634f692ef0937b5a9c5 100644 (file)
@@ -248,8 +248,7 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
        else
                q->queuedata = shost;
 
-       set_bit(QUEUE_FLAG_BIDI, &q->queue_flags);
-
+       queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q);
        return 0;
 }
 
index 3cea17dd5dbac5b80619e9ee7a34732401ee586d..01cefbb2d5396718f61ed49e188c05b1e2772925 100644 (file)
@@ -860,7 +860,6 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
 
 static void sd_prepare_flush(struct request_queue *q, struct request *rq)
 {
-       memset(rq->cmd, 0, sizeof(rq->cmd));
        rq->cmd_type = REQ_TYPE_BLOCK_PC;
        rq->timeout = SD_TIMEOUT;
        rq->cmd[0] = SYNCHRONIZE_CACHE;
index 2029422bc04d099ba081df55b73cd94a940390d5..c9d7f721b9e28005fcba109b974ed6216e58c8e8 100644 (file)
@@ -2667,7 +2667,6 @@ sg_proc_init(void)
 {
        int k, mask;
        int num_leaves = ARRAY_SIZE(sg_proc_leaf_arr);
-       struct proc_dir_entry *pdep;
        struct sg_proc_leaf * leaf;
 
        sg_proc_sgp = proc_mkdir(sg_proc_sg_dirname, NULL);
@@ -2676,13 +2675,10 @@ sg_proc_init(void)
        for (k = 0; k < num_leaves; ++k) {
                leaf = &sg_proc_leaf_arr[k];
                mask = leaf->fops->write ? S_IRUGO | S_IWUSR : S_IRUGO;
-               pdep = create_proc_entry(leaf->name, mask, sg_proc_sgp);
-               if (pdep) {
-                       leaf->fops->owner = THIS_MODULE,
-                       leaf->fops->read = seq_read,
-                       leaf->fops->llseek = seq_lseek,
-                       pdep->proc_fops = leaf->fops;
-               }
+               leaf->fops->owner = THIS_MODULE;
+               leaf->fops->read = seq_read;
+               leaf->fops->llseek = seq_lseek;
+               proc_create(leaf->name, mask, sg_proc_sgp, leaf->fops);
        }
        return 0;
 }
index 2b8a410e09595f87bffd264a44ce0a840cde599d..bbf5bc5892c7be21451fa55c6863af71519ffaff 100644 (file)
@@ -200,7 +200,7 @@ static void rs_stop(struct tty_struct *tty)
        local_irq_restore(flags);
 }
 
-static void rs_put_char(char ch)
+static int rs_put_char(char ch)
 {
         int flags, loops = 0;
 
@@ -214,6 +214,7 @@ static void rs_put_char(char ch)
        UTX_TXDATA = ch;
         udelay(5);
         local_irq_restore(flags);
+        return 1;
 }
 
 static void rs_start(struct tty_struct *tty)
@@ -1017,18 +1018,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
                        tty_wait_until_sent(tty, 0);
                        send_break(info, arg ? arg*(100) : 250);
                        return 0;
-               case TIOCGSOFTCAR:
-                       error = put_user(C_CLOCAL(tty) ? 1 : 0,
-                                   (unsigned long *) arg);
-                       if (error)
-                               return error;
-                       return 0;
-               case TIOCSSOFTCAR:
-                       get_user(arg, (unsigned long *) arg);
-                       tty->termios->c_cflag =
-                               ((tty->termios->c_cflag & ~CLOCAL) |
-                                (arg ? CLOCAL : 0));
-                       return 0;
                case TIOCGSERIAL:
                        if (access_ok(VERIFY_WRITE, (void *) arg,
                                                sizeof(struct serial_struct)))
@@ -1061,9 +1050,6 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
 
-       if (tty->termios->c_cflag == old_termios->c_cflag)
-               return;
-
        change_speed(info);
 
        if ((old_termios->c_cflag & CRTSCTS) &&
@@ -1140,8 +1126,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
        uart->ustcnt &= ~(USTCNT_RXEN | USTCNT_RX_INTR_MASK);
 
        shutdown(info);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       rs_flush_buffer(tty);
                
        tty_ldisc_flush(tty);
        tty->closing = 0;
index f5946360187448ea65fd7996dbeb28ccb71279a0..d9d4e9552a4d355c2458749621cf9d83898db86d 100644 (file)
@@ -995,10 +995,10 @@ static void rs_360_put_char(struct tty_struct *tty, unsigned char ch)
        volatile QUICC_BD       *bdp;
 
        if (serial_paranoia_check(info, tty->name, "rs_put_char"))
-               return;
+               return 0;
 
        if (!tty)
-               return;
+               return 0;
 
        bdp = info->tx_cur;
        while (bdp->status & BD_SC_READY);
@@ -1016,6 +1016,7 @@ static void rs_360_put_char(struct tty_struct *tty, unsigned char ch)
                bdp++;
 
        info->tx_cur = (QUICC_BD *)bdp;
+       return 1;
 
 }
 
@@ -1246,7 +1247,7 @@ static int rs_360_tiocmget(struct tty_struct *tty, struct file *file)
 #ifdef modem_control
        unsigned char control, status;
 
-       if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+       if (serial_paranoia_check(info, tty->name, __func__))
                return -ENODEV;
 
        if (tty->flags & (1 << TTY_IO_ERROR))
@@ -1277,12 +1278,12 @@ static int rs_360_tiocmset(struct tty_struct *tty, struct file *file,
        ser_info_t *info = (ser_info_t *)tty->driver_data;
        unsigned int arg;
 
-       if (serial_paranoia_check(info, tty->name, __FUNCTION__))
+       if (serial_paranoia_check(info, tty->name, __func__))
                return -ENODEV;
 
        if (tty->flags & (1 << TTY_IO_ERROR))
                return -EIO;
-
+       /* FIXME: locking on info->mcr */
        if (set & TIOCM_RTS)
                info->mcr |= UART_MCR_RTS;
        if (set & TIOCM_DTR)
@@ -1436,18 +1437,6 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
                                return retval;
                        end_break(info);
                        return 0;
-               case TIOCGSOFTCAR:
-                       /* return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg); */
-                       put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg);
-                       return 0;
-               case TIOCSSOFTCAR:
-                       error = get_user(arg, (unsigned int *) arg); 
-                       if (error)
-                               return error;
-                       tty->termios->c_cflag =
-                               ((tty->termios->c_cflag & ~CLOCAL) |
-                                (arg ? CLOCAL : 0));
-                       return 0;
 #ifdef maybe
                case TIOCSERGETLSR: /* Get line status register */
                        return get_lsr_info(info, (unsigned int *) arg);
@@ -1665,8 +1654,7 @@ static void rs_360_close(struct tty_struct *tty, struct file * filp)
                rs_360_wait_until_sent(tty, info->timeout);
        }
        shutdown(info);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       rs_360_flush_buffer(tty);
        tty_ldisc_flush(tty);           
        tty->closing = 0;
        info->event = 0;
@@ -1717,6 +1705,7 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout)
        printk("jiff=%lu...", jiffies);
 #endif
 
+       lock_kernel();
        /* We go through the loop at least once because we can't tell
         * exactly when the last character exits the shifter.  There can
         * be at least two characters waiting to be sent after the buffers
@@ -1745,6 +1734,7 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout)
                        bdp--;
        } while (bdp->status & BD_SC_READY);
        current->state = TASK_RUNNING;
+       unlock_kernel();
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
        printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
 #endif
index 38776e8b064b07f57f8815709efd70defeb9d4ca..cd898704ba4f66d5fba055d4e9d574e5125786cd 100644 (file)
@@ -156,7 +156,7 @@ static int __init parse_options(struct early_serial8250_device *device,
                port->membase = ioremap(port->mapbase, 64);
                if (!port->membase) {
                        printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n",
-                               __FUNCTION__,
+                               __func__,
                               (unsigned long long)port->mapbase);
                        return -ENOMEM;
                }
index 34b809e3b59651dd17ec404ebd3bc9a1be0a421a..36acbcca2d4893c4aa3178e0d7e426cff2029f90 100644 (file)
@@ -1355,4 +1355,47 @@ config SERIAL_SC26XX_CONSOLE
        help
          Support for Console on SC2681/SC2692 serial ports.
 
+config SERIAL_BFIN_SPORT
+       tristate "Blackfin SPORT emulate UART (EXPERIMENTAL)"
+       depends on BFIN && EXPERIMENTAL
+       select SERIAL_CORE
+       help
+         Enble support SPORT emulate UART on Blackfin series.
+
+         To compile this driver as a module, choose M here: the
+         module will be called bfin_sport_uart.
+
+choice
+       prompt "Baud rate for Blackfin SPORT UART"
+       depends on SERIAL_BFIN_SPORT
+       default SERIAL_SPORT_BAUD_RATE_57600
+       help
+         Choose a baud rate for the SPORT UART, other uart settings are
+         8 bit, 1 stop bit, no parity, no flow control.
+
+config SERIAL_SPORT_BAUD_RATE_115200
+       bool "115200"
+
+config SERIAL_SPORT_BAUD_RATE_57600
+       bool "57600"
+
+config SERIAL_SPORT_BAUD_RATE_38400
+       bool "38400"
+
+config SERIAL_SPORT_BAUD_RATE_19200
+       bool "19200"
+
+config SERIAL_SPORT_BAUD_RATE_9600
+       bool "9600"
+endchoice
+
+config SPORT_BAUD_RATE
+       int
+       depends on SERIAL_BFIN_SPORT
+       default 115200 if (SERIAL_SPORT_BAUD_RATE_115200)
+       default 57600 if (SERIAL_SPORT_BAUD_RATE_57600)
+       default 38400 if (SERIAL_SPORT_BAUD_RATE_38400)
+       default 19200 if (SERIAL_SPORT_BAUD_RATE_19200)
+       default 9600 if (SERIAL_SPORT_BAUD_RATE_9600)
+
 endmenu
index f02ff9fad017de0dbcd6b7396f72141ec34e32c9..0d9c09b1e8367489b98bede96e59d2ee2f6b693e 100644 (file)
@@ -27,6 +27,7 @@ obj-$(CONFIG_SERIAL_PXA) += pxa.o
 obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o
 obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
 obj-$(CONFIG_SERIAL_BFIN) += bfin_5xx.o
+obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o
 obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
 obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o
 obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o
index 5f55534a290ba8d00000c694cef8c28496347090..8a2f6a1baa74d5b09b31666dd46be9b7bca746c2 100644 (file)
@@ -762,7 +762,7 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
                break;
        default:
                printk(KERN_ERR "%s: word lengh not supported\n",
-                       __FUNCTION__);
+                       __func__);
        }
 
        if (termios->c_cflag & CSTOPB)
@@ -1029,7 +1029,7 @@ bfin_serial_console_get_options(struct bfin_serial_port *uart, int *baud,
 
                *baud = get_sclk() / (16*(dll | dlh << 8));
        }
-       pr_debug("%s:baud = %d, parity = %c, bits= %d\n", __FUNCTION__, *baud, *parity, *bits);
+       pr_debug("%s:baud = %d, parity = %c, bits= %d\n", __func__, *baud, *parity, *bits);
 }
 #endif
 
diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c
new file mode 100644 (file)
index 0000000..aca1240
--- /dev/null
@@ -0,0 +1,614 @@
+/*
+ * File:       linux/drivers/serial/bfin_sport_uart.c
+ *
+ * Based on:   drivers/serial/bfin_5xx.c by Aubrey Li.
+ * Author:     Roy Huang <roy.huang@analog.com>
+ *
+ * Created:    Nov 22, 2006
+ * Copyright:  (c) 2006-2007 Analog Devices Inc.
+ * Description: this driver enable SPORTs on Blackfin emulate UART.
+ *
+ * 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * This driver and the hardware supported are in term of EE-191 of ADI.
+ * http://www.analog.com/UploadedFiles/Application_Notes/399447663EE191.pdf
+ * This application note describe how to implement a UART on a Sharc DSP,
+ * but this driver is implemented on Blackfin Processor.
+ */
+
+/* After reset, there is a prelude of low level pulse when transmit data first
+ * time. No addtional pulse in following transmit.
+ * According to document:
+ * The SPORTs are ready to start transmitting or receiving data no later than
+ * three serial clock cycles after they are enabled in the SPORTx_TCR1 or
+ * SPORTx_RCR1 register. No serial clock cycles are lost from this point on.
+ * The first internal frame sync will occur one frame sync delay after the
+ * SPORTs are ready. External frame syncs can occur as soon as the SPORT is
+ * ready.
+ */
+
+/* Thanks to Axel Alatalo <axel@rubico.se> for fixing sport rx bug. Sometimes
+ * sport receives data incorrectly. The following is Axel's words.
+ * As EE-191, sport rx samples 3 times of the UART baudrate and takes the
+ * middle smaple of every 3 samples as the data bit. For a 8-N-1 UART setting,
+ * 30 samples will be required for a byte. If transmitter sends a 1/3 bit short
+ * byte due to buadrate drift, then the 30th sample of a byte, this sample is
+ * also the third sample of the stop bit, will happens on the immediately
+ * following start bit which will be thrown away and missed. Thus since parts
+ * of the startbit will be missed and the receiver will begin to drift, the
+ * effect accumulates over time until synchronization is lost.
+ * If only require 2 samples of the stopbit (by sampling in total 29 samples),
+ * then a to short byte as in the case above will be tolerated. Then the 1/3
+ * early startbit will trigger a framesync since the last read is complete
+ * after only 2/3 stopbit and framesync is active during the last 1/3 looking
+ * for a possible early startbit. */
+
+//#define DEBUG
+
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/platform_device.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+
+#include <asm/delay.h>
+#include <asm/portmux.h>
+
+#include "bfin_sport_uart.h"
+
+unsigned short bfin_uart_pin_req_sport0[] =
+       {P_SPORT0_TFS, P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, \
+        P_SPORT0_DRPRI, P_SPORT0_RSCLK, P_SPORT0_DRSEC, P_SPORT0_DTSEC, 0};
+
+unsigned short bfin_uart_pin_req_sport1[] =
+       {P_SPORT1_TFS, P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, \
+       P_SPORT1_DRPRI, P_SPORT1_RSCLK, P_SPORT1_DRSEC, P_SPORT1_DTSEC, 0};
+
+#define DRV_NAME "bfin-sport-uart"
+
+struct sport_uart_port {
+       struct uart_port        port;
+       char                    *name;
+
+       int                     tx_irq;
+       int                     rx_irq;
+       int                     err_irq;
+};
+
+static void sport_uart_tx_chars(struct sport_uart_port *up);
+static void sport_stop_tx(struct uart_port *port);
+
+static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value)
+{
+       pr_debug("%s value:%x\n", __FUNCTION__, value);
+       /* Place a Start and Stop bit */
+       __asm__ volatile (
+               "R2 = b#01111111100;\n\t"
+               "R3 = b#10000000001;\n\t"
+               "%0 <<= 2;\n\t"
+               "%0 = %0 & R2;\n\t"
+               "%0 = %0 | R3;\n\t"
+               :"=r"(value)
+               :"0"(value)
+               :"R2", "R3");
+       pr_debug("%s value:%x\n", __FUNCTION__, value);
+
+       SPORT_PUT_TX(up, value);
+}
+
+static inline unsigned int rx_one_byte(struct sport_uart_port *up)
+{
+       unsigned int value, extract;
+
+       value = SPORT_GET_RX32(up);
+       pr_debug("%s value:%x\n", __FUNCTION__, value);
+
+       /* Extract 8 bits data */
+       __asm__ volatile (
+               "R5 = 0;\n\t"
+               "P0 = 8;\n\t"
+               "R1 = 0x1801(Z);\n\t"
+               "R3 = 0x0300(Z);\n\t"
+               "R4 = 0;\n\t"
+               "LSETUP(loop_s, loop_e) LC0 = P0;\nloop_s:\t"
+               "R2 = extract(%1, R1.L)(Z);\n\t"
+               "R2 <<= R4;\n\t"
+               "R5 = R5 | R2;\n\t"
+               "R1 = R1 - R3;\nloop_e:\t"
+               "R4 += 1;\n\t"
+               "%0 = R5;\n\t"
+               :"=r"(extract)
+               :"r"(value)
+               :"P0", "R1", "R2","R3","R4", "R5");
+
+       pr_debug("      extract:%x\n", extract);
+       return extract;
+}
+
+static int sport_uart_setup(struct sport_uart_port *up, int sclk, int baud_rate)
+{
+       int tclkdiv, tfsdiv, rclkdiv;
+
+       /* Set TCR1 and TCR2 */
+       SPORT_PUT_TCR1(up, (LTFS | ITFS | TFSR | TLSBIT | ITCLK));
+       SPORT_PUT_TCR2(up, 10);
+       pr_debug("%s TCR1:%x, TCR2:%x\n", __FUNCTION__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up));
+
+       /* Set RCR1 and RCR2 */
+       SPORT_PUT_RCR1(up, (RCKFE | LARFS | LRFS | RFSR | IRCLK));
+       SPORT_PUT_RCR2(up, 28);
+       pr_debug("%s RCR1:%x, RCR2:%x\n", __FUNCTION__, SPORT_GET_RCR1(up), SPORT_GET_RCR2(up));
+
+       tclkdiv = sclk/(2 * baud_rate) - 1;
+       tfsdiv = 12;
+       rclkdiv = sclk/(2 * baud_rate * 3) - 1;
+       SPORT_PUT_TCLKDIV(up, tclkdiv);
+       SPORT_PUT_TFSDIV(up, tfsdiv);
+       SPORT_PUT_RCLKDIV(up, rclkdiv);
+       SSYNC();
+       pr_debug("%s sclk:%d, baud_rate:%d, tclkdiv:%d, tfsdiv:%d, rclkdiv:%d\n",
+                       __FUNCTION__, sclk, baud_rate, tclkdiv, tfsdiv, rclkdiv);
+
+       return 0;
+}
+
+static irqreturn_t sport_uart_rx_irq(int irq, void *dev_id)
+{
+       struct sport_uart_port *up = dev_id;
+       struct tty_struct *tty = up->port.info->tty;
+       unsigned int ch;
+
+       do {
+               ch = rx_one_byte(up);
+               up->port.icount.rx++;
+
+               if (uart_handle_sysrq_char(&up->port, ch))
+                       ;
+               else
+                       tty_insert_flip_char(tty, ch, TTY_NORMAL);
+       } while (SPORT_GET_STAT(up) & RXNE);
+       tty_flip_buffer_push(tty);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t sport_uart_tx_irq(int irq, void *dev_id)
+{
+       sport_uart_tx_chars(dev_id);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t sport_uart_err_irq(int irq, void *dev_id)
+{
+       struct sport_uart_port *up = dev_id;
+       struct tty_struct *tty = up->port.info->tty;
+       unsigned int stat = SPORT_GET_STAT(up);
+
+       /* Overflow in RX FIFO */
+       if (stat & ROVF) {
+               up->port.icount.overrun++;
+               tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+               SPORT_PUT_STAT(up, ROVF); /* Clear ROVF bit */
+       }
+       /* These should not happen */
+       if (stat & (TOVF | TUVF | RUVF)) {
+               printk(KERN_ERR "SPORT Error:%s %s %s\n",
+                               (stat & TOVF)?"TX overflow":"",
+                               (stat & TUVF)?"TX underflow":"",
+                               (stat & RUVF)?"RX underflow":"");
+               SPORT_PUT_TCR1(up, SPORT_GET_TCR1(up) & ~TSPEN);
+               SPORT_PUT_RCR1(up, SPORT_GET_RCR1(up) & ~RSPEN);
+       }
+       SSYNC();
+
+       return IRQ_HANDLED;
+}
+
+/* Reqeust IRQ, Setup clock */
+static int sport_startup(struct uart_port *port)
+{
+       struct sport_uart_port *up = (struct sport_uart_port *)port;
+       char buffer[20];
+       int retval;
+
+       pr_debug("%s enter\n", __FUNCTION__);
+       memset(buffer, 20, '\0');
+       snprintf(buffer, 20, "%s rx", up->name);
+       retval = request_irq(up->rx_irq, sport_uart_rx_irq, IRQF_SAMPLE_RANDOM, buffer, up);
+       if (retval) {
+               printk(KERN_ERR "Unable to request interrupt %s\n", buffer);
+               return retval;
+       }
+
+       snprintf(buffer, 20, "%s tx", up->name);
+       retval = request_irq(up->tx_irq, sport_uart_tx_irq, IRQF_SAMPLE_RANDOM, buffer, up);
+       if (retval) {
+               printk(KERN_ERR "Unable to request interrupt %s\n", buffer);
+               goto fail1;
+       }
+
+       snprintf(buffer, 20, "%s err", up->name);
+       retval = request_irq(up->err_irq, sport_uart_err_irq, IRQF_SAMPLE_RANDOM, buffer, up);
+       if (retval) {
+               printk(KERN_ERR "Unable to request interrupt %s\n", buffer);
+               goto fail2;
+       }
+
+       if (port->line) {
+               if (peripheral_request_list(bfin_uart_pin_req_sport1, DRV_NAME))
+                       goto fail3;
+       } else {
+               if (peripheral_request_list(bfin_uart_pin_req_sport0, DRV_NAME))
+                       goto fail3;
+       }
+
+       sport_uart_setup(up, get_sclk(), port->uartclk);
+
+       /* Enable receive interrupt */
+       SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) | RSPEN));
+       SSYNC();
+
+       return 0;
+
+
+fail3:
+       printk(KERN_ERR DRV_NAME
+               ": Requesting Peripherals failed\n");
+
+       free_irq(up->err_irq, up);
+fail2:
+       free_irq(up->tx_irq, up);
+fail1:
+       free_irq(up->rx_irq, up);
+
+       return retval;
+
+}
+
+static void sport_uart_tx_chars(struct sport_uart_port *up)
+{
+       struct circ_buf *xmit = &up->port.info->xmit;
+
+       if (SPORT_GET_STAT(up) & TXF)
+               return;
+
+       if (up->port.x_char) {
+               tx_one_byte(up, up->port.x_char);
+               up->port.icount.tx++;
+               up->port.x_char = 0;
+               return;
+       }
+
+       if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
+               sport_stop_tx(&up->port);
+               return;
+       }
+
+       while(!(SPORT_GET_STAT(up) & TXF) && !uart_circ_empty(xmit)) {
+               tx_one_byte(up, xmit->buf[xmit->tail]);
+               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE -1);
+               up->port.icount.tx++;
+       }
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(&up->port);
+}
+
+static unsigned int sport_tx_empty(struct uart_port *port)
+{
+       struct sport_uart_port *up = (struct sport_uart_port *)port;
+       unsigned int stat;
+
+       stat = SPORT_GET_STAT(up);
+       pr_debug("%s stat:%04x\n", __FUNCTION__, stat);
+       if (stat & TXHRE) {
+               return TIOCSER_TEMT;
+       } else
+               return 0;
+}
+
+static unsigned int sport_get_mctrl(struct uart_port *port)
+{
+       pr_debug("%s enter\n", __FUNCTION__);
+       return (TIOCM_CTS | TIOCM_CD | TIOCM_DSR);
+}
+
+static void sport_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+       pr_debug("%s enter\n", __FUNCTION__);
+}
+
+static void sport_stop_tx(struct uart_port *port)
+{
+       struct sport_uart_port *up = (struct sport_uart_port *)port;
+       unsigned int stat;
+
+       pr_debug("%s enter\n", __FUNCTION__);
+
+       stat = SPORT_GET_STAT(up);
+       while(!(stat & TXHRE)) {
+               udelay(1);
+               stat = SPORT_GET_STAT(up);
+       }
+       /* Although the hold register is empty, last byte is still in shift
+        * register and not sent out yet. If baud rate is lower than default,
+        * delay should be longer. For example, if the baud rate is 9600,
+        * the delay must be at least 2ms by experience */
+       udelay(500);
+
+       SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN));
+       SSYNC();
+
+       return;
+}
+
+static void sport_start_tx(struct uart_port *port)
+{
+       struct sport_uart_port *up = (struct sport_uart_port *)port;
+
+       pr_debug("%s enter\n", __FUNCTION__);
+       /* Write data into SPORT FIFO before enable SPROT to transmit */
+       sport_uart_tx_chars(up);
+
+       /* Enable transmit, then an interrupt will generated */
+       SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) | TSPEN));
+       SSYNC();
+       pr_debug("%s exit\n", __FUNCTION__);
+}
+
+static void sport_stop_rx(struct uart_port *port)
+{
+       struct sport_uart_port *up = (struct sport_uart_port *)port;
+
+       pr_debug("%s enter\n", __FUNCTION__);
+       /* Disable sport to stop rx */
+       SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) & ~RSPEN));
+       SSYNC();
+}
+
+static void sport_enable_ms(struct uart_port *port)
+{
+       pr_debug("%s enter\n", __FUNCTION__);
+}
+
+static void sport_break_ctl(struct uart_port *port, int break_state)
+{
+       pr_debug("%s enter\n", __FUNCTION__);
+}
+
+static void sport_shutdown(struct uart_port *port)
+{
+       struct sport_uart_port *up = (struct sport_uart_port *)port;
+
+       pr_debug("%s enter\n", __FUNCTION__);
+
+       /* Disable sport */
+       SPORT_PUT_TCR1(up, (SPORT_GET_TCR1(up) & ~TSPEN));
+       SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) & ~RSPEN));
+       SSYNC();
+
+       if (port->line) {
+               peripheral_free_list(bfin_uart_pin_req_sport1);
+       } else {
+               peripheral_free_list(bfin_uart_pin_req_sport0);
+       }
+
+       free_irq(up->rx_irq, up);
+       free_irq(up->tx_irq, up);
+       free_irq(up->err_irq, up);
+}
+
+static void sport_set_termios(struct uart_port *port,
+               struct termios *termios, struct termios *old)
+{
+       pr_debug("%s enter, c_cflag:%08x\n", __FUNCTION__, termios->c_cflag);
+       uart_update_timeout(port, CS8 ,port->uartclk);
+}
+
+static const char *sport_type(struct uart_port *port)
+{
+       struct sport_uart_port *up = (struct sport_uart_port *)port;
+
+       pr_debug("%s enter\n", __FUNCTION__);
+       return up->name;
+}
+
+static void sport_release_port(struct uart_port *port)
+{
+       pr_debug("%s enter\n", __FUNCTION__);
+}
+
+static int sport_request_port(struct uart_port *port)
+{
+       pr_debug("%s enter\n", __FUNCTION__);
+       return 0;
+}
+
+static void sport_config_port(struct uart_port *port, int flags)
+{
+       struct sport_uart_port *up = (struct sport_uart_port *)port;
+
+       pr_debug("%s enter\n", __FUNCTION__);
+       up->port.type = PORT_BFIN_SPORT;
+}
+
+static int sport_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+       pr_debug("%s enter\n", __FUNCTION__);
+       return 0;
+}
+
+struct uart_ops sport_uart_ops = {
+       .tx_empty       = sport_tx_empty,
+       .set_mctrl      = sport_set_mctrl,
+       .get_mctrl      = sport_get_mctrl,
+       .stop_tx        = sport_stop_tx,
+       .start_tx       = sport_start_tx,
+       .stop_rx        = sport_stop_rx,
+       .enable_ms      = sport_enable_ms,
+       .break_ctl      = sport_break_ctl,
+       .startup        = sport_startup,
+       .shutdown       = sport_shutdown,
+       .set_termios    = sport_set_termios,
+       .type           = sport_type,
+       .release_port   = sport_release_port,
+       .request_port   = sport_request_port,
+       .config_port    = sport_config_port,
+       .verify_port    = sport_verify_port,
+};
+
+static struct sport_uart_port sport_uart_ports[] = {
+       { /* SPORT 0 */
+               .name   = "SPORT0",
+               .tx_irq = IRQ_SPORT0_TX,
+               .rx_irq = IRQ_SPORT0_RX,
+               .err_irq= IRQ_SPORT0_ERROR,
+               .port   = {
+                       .type           = PORT_BFIN_SPORT,
+                       .iotype         = UPIO_MEM,
+                       .membase        = (void __iomem *)SPORT0_TCR1,
+                       .mapbase        = SPORT0_TCR1,
+                       .irq            = IRQ_SPORT0_RX,
+                       .uartclk        = CONFIG_SPORT_BAUD_RATE,
+                       .fifosize       = 8,
+                       .ops            = &sport_uart_ops,
+                       .line           = 0,
+               },
+       }, { /* SPORT 1 */
+               .name   = "SPORT1",
+               .tx_irq = IRQ_SPORT1_TX,
+               .rx_irq = IRQ_SPORT1_RX,
+               .err_irq= IRQ_SPORT1_ERROR,
+               .port   = {
+                       .type           = PORT_BFIN_SPORT,
+                       .iotype         = UPIO_MEM,
+                       .membase        = (void __iomem *)SPORT1_TCR1,
+                       .mapbase        = SPORT1_TCR1,
+                       .irq            = IRQ_SPORT1_RX,
+                       .uartclk        = CONFIG_SPORT_BAUD_RATE,
+                       .fifosize       = 8,
+                       .ops            = &sport_uart_ops,
+                       .line           = 1,
+               },
+       }
+};
+
+static struct uart_driver sport_uart_reg = {
+       .owner          = THIS_MODULE,
+       .driver_name    = "SPORT-UART",
+       .dev_name       = "ttySS",
+       .major          = 204,
+       .minor          = 84,
+       .nr             = ARRAY_SIZE(sport_uart_ports),
+       .cons           = NULL,
+};
+
+static int sport_uart_suspend(struct platform_device *dev, pm_message_t state)
+{
+       struct sport_uart_port *sport = platform_get_drvdata(dev);
+
+       pr_debug("%s enter\n", __FUNCTION__);
+       if (sport)
+               uart_suspend_port(&sport_uart_reg, &sport->port);
+
+       return 0;
+}
+
+static int sport_uart_resume(struct platform_device *dev)
+{
+       struct sport_uart_port *sport = platform_get_drvdata(dev);
+
+       pr_debug("%s enter\n", __FUNCTION__);
+       if (sport)
+               uart_resume_port(&sport_uart_reg, &sport->port);
+
+       return 0;
+}
+
+static int sport_uart_probe(struct platform_device *dev)
+{
+       pr_debug("%s enter\n", __FUNCTION__);
+       sport_uart_ports[dev->id].port.dev = &dev->dev;
+       uart_add_one_port(&sport_uart_reg, &sport_uart_ports[dev->id].port);
+       platform_set_drvdata(dev, &sport_uart_ports[dev->id]);
+
+       return 0;
+}
+
+static int sport_uart_remove(struct platform_device *dev)
+{
+       struct sport_uart_port *sport = platform_get_drvdata(dev);
+
+       pr_debug("%s enter\n", __FUNCTION__);
+       platform_set_drvdata(dev, NULL);
+
+       if (sport)
+               uart_remove_one_port(&sport_uart_reg, &sport->port);
+
+       return 0;
+}
+
+static struct platform_driver sport_uart_driver = {
+       .probe          = sport_uart_probe,
+       .remove         = sport_uart_remove,
+       .suspend        = sport_uart_suspend,
+       .resume         = sport_uart_resume,
+       .driver         = {
+               .name   = DRV_NAME,
+       },
+};
+
+static int __init sport_uart_init(void)
+{
+       int ret;
+
+       pr_debug("%s enter\n", __FUNCTION__);
+       ret = uart_register_driver(&sport_uart_reg);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register %s:%d\n",
+                               sport_uart_reg.driver_name, ret);
+               return ret;
+       }
+
+       ret = platform_driver_register(&sport_uart_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register sport uart driver:%d\n", ret);
+               uart_unregister_driver(&sport_uart_reg);
+       }
+
+
+       pr_debug("%s exit\n", __FUNCTION__);
+       return ret;
+}
+
+static void __exit sport_uart_exit(void)
+{
+       pr_debug("%s enter\n", __FUNCTION__);
+       platform_driver_unregister(&sport_uart_driver);
+       uart_unregister_driver(&sport_uart_reg);
+}
+
+module_init(sport_uart_init);
+module_exit(sport_uart_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/serial/bfin_sport_uart.h b/drivers/serial/bfin_sport_uart.h
new file mode 100644 (file)
index 0000000..671d41c
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * File:       linux/drivers/serial/bfin_sport_uart.h
+ *
+ * Based on:   include/asm-blackfin/mach-533/bfin_serial_5xx.h
+ * Author:     Roy Huang <roy.huang>analog.com>
+ *
+ * Created:    Nov 22, 2006
+ * Copyright:  (C) Analog Device Inc.
+ * Description: this driver enable SPORTs on Blackfin emulate UART.
+ *
+ * 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#define OFFSET_TCR1            0x00    /* Transmit Configuration 1 Register */
+#define OFFSET_TCR2            0x04    /* Transmit Configuration 2 Register */
+#define OFFSET_TCLKDIV         0x08    /* Transmit Serial Clock Divider Register */
+#define OFFSET_TFSDIV          0x0C    /* Transmit Frame Sync Divider Register */
+#define OFFSET_TX              0x10    /* Transmit Data Register               */
+#define OFFSET_RX              0x18    /* Receive Data Register                */
+#define OFFSET_RCR1            0x20    /* Receive Configuration 1 Register     */
+#define OFFSET_RCR2            0x24    /* Receive Configuration 2 Register     */
+#define OFFSET_RCLKDIV         0x28    /* Receive Serial Clock Divider Register */
+#define OFFSET_RFSDIV          0x2c    /* Receive Frame Sync Divider Register */
+#define OFFSET_STAT            0x30    /* Status Register                      */
+
+#define SPORT_GET_TCR1(sport)          bfin_read16(((sport)->port.membase + OFFSET_TCR1))
+#define SPORT_GET_TCR2(sport)          bfin_read16(((sport)->port.membase + OFFSET_TCR2))
+#define SPORT_GET_TCLKDIV(sport)       bfin_read16(((sport)->port.membase + OFFSET_TCLKDIV))
+#define SPORT_GET_TFSDIV(sport)                bfin_read16(((sport)->port.membase + OFFSET_TFSDIV))
+#define SPORT_GET_TX(sport)            bfin_read16(((sport)->port.membase + OFFSET_TX))
+#define SPORT_GET_RX(sport)            bfin_read16(((sport)->port.membase + OFFSET_RX))
+#define SPORT_GET_RX32(sport)          bfin_read32(((sport)->port.membase + OFFSET_RX))
+#define SPORT_GET_RCR1(sport)          bfin_read16(((sport)->port.membase + OFFSET_RCR1))
+#define SPORT_GET_RCR2(sport)          bfin_read16(((sport)->port.membase + OFFSET_RCR2))
+#define SPORT_GET_RCLKDIV(sport)       bfin_read16(((sport)->port.membase + OFFSET_RCLKDIV))
+#define SPORT_GET_RFSDIV(sport)                bfin_read16(((sport)->port.membase + OFFSET_RFSDIV))
+#define SPORT_GET_STAT(sport)          bfin_read16(((sport)->port.membase + OFFSET_STAT))
+
+#define SPORT_PUT_TCR1(sport, v)       bfin_write16(((sport)->port.membase + OFFSET_TCR1), v)
+#define SPORT_PUT_TCR2(sport, v)       bfin_write16(((sport)->port.membase + OFFSET_TCR2), v)
+#define SPORT_PUT_TCLKDIV(sport, v)    bfin_write16(((sport)->port.membase + OFFSET_TCLKDIV), v)
+#define SPORT_PUT_TFSDIV(sport, v)     bfin_write16(((sport)->port.membase + OFFSET_TFSDIV), v)
+#define SPORT_PUT_TX(sport, v)         bfin_write16(((sport)->port.membase + OFFSET_TX), v)
+#define SPORT_PUT_RX(sport, v)         bfin_write16(((sport)->port.membase + OFFSET_RX), v)
+#define SPORT_PUT_RCR1(sport, v)       bfin_write16(((sport)->port.membase + OFFSET_RCR1), v)
+#define SPORT_PUT_RCR2(sport, v)       bfin_write16(((sport)->port.membase + OFFSET_RCR2), v)
+#define SPORT_PUT_RCLKDIV(sport, v)    bfin_write16(((sport)->port.membase + OFFSET_RCLKDIV), v)
+#define SPORT_PUT_RFSDIV(sport, v)     bfin_write16(((sport)->port.membase + OFFSET_RFSDIV), v)
+#define SPORT_PUT_STAT(sport, v)       bfin_write16(((sport)->port.membase + OFFSET_STAT), v)
index a638ba0679ac0f5f2342b4867c1cb5457a5e7c23..a19dc7ef88611f46a382c9227c94238d5e8ed25a 100644 (file)
@@ -1117,7 +1117,7 @@ int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con)
 
        line = cpm_uart_id2nr(idx);
        if(line < 0) {
-               printk(KERN_ERR"%s(): port %d is not registered", __FUNCTION__, idx);
+               printk(KERN_ERR"%s(): port %d is not registered", __func__, idx);
                return -EINVAL;
        }
 
index 88e7c1d5b919f455b47658367b9b7d835d849ba9..f9fa237aa9496d7cdf88d4cd0589d8b8391ae351 100644 (file)
@@ -1788,7 +1788,7 @@ static unsigned int handle_descr_data(struct e100_serial *info,
 
        if (info->recv_cnt + recvl > 65536) {
                printk(KERN_CRIT
-                      "%s: Too much pending incoming serial data! Dropping %u bytes.\n", __FUNCTION__, recvl);
+                      "%s: Too much pending incoming serial data! Dropping %u bytes.\n", __func__, recvl);
                return 0;
        }
 
@@ -1801,7 +1801,7 @@ static unsigned int handle_descr_data(struct e100_serial *info,
        append_recv_buffer(info, buffer);
 
        if (!(buffer = alloc_recv_buffer(SERIAL_DESCR_BUF_SIZE)))
-               panic("%s: Failed to allocate memory for receive buffer!\n", __FUNCTION__);
+               panic("%s: Failed to allocate memory for receive buffer!\n", __func__);
 
        descr->buf = virt_to_phys(buffer->buffer);
 
@@ -1925,7 +1925,7 @@ static int start_recv_dma(struct e100_serial *info)
        /* Set up the receiving descriptors */
        for (i = 0; i < SERIAL_RECV_DESCRIPTORS; i++) {
                if (!(buffer = alloc_recv_buffer(SERIAL_DESCR_BUF_SIZE)))
-                       panic("%s: Failed to allocate memory for receive buffer!\n", __FUNCTION__);
+                       panic("%s: Failed to allocate memory for receive buffer!\n", __func__);
 
                descr[i].ctrl = d_int;
                descr[i].buf = virt_to_phys(buffer->buffer);
@@ -3581,8 +3581,9 @@ rs_tiocmset(struct tty_struct *tty, struct file *file,
                unsigned int set, unsigned int clear)
 {
        struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+       unsigned long flags;
 
-       lock_kernel();
+       local_irq_save(flags);
 
        if (clear & TIOCM_RTS)
                e100_rts(info, 0);
@@ -3604,7 +3605,7 @@ rs_tiocmset(struct tty_struct *tty, struct file *file,
        if (set & TIOCM_CD)
                e100_cd_out(info, 1);
 
-       unlock_kernel();
+       local_irq_restore(flags);
        return 0;
 }
 
@@ -3613,8 +3614,10 @@ rs_tiocmget(struct tty_struct *tty, struct file *file)
 {
        struct e100_serial *info = (struct e100_serial *)tty->driver_data;
        unsigned int result;
+       unsigned long flags;
+
+       local_irq_save(flags);
 
-       lock_kernel();
        result =
                (!E100_RTS_GET(info) ? TIOCM_RTS : 0)
                | (!E100_DTR_GET(info) ? TIOCM_DTR : 0)
@@ -3623,7 +3626,7 @@ rs_tiocmget(struct tty_struct *tty, struct file *file)
                | (!E100_CD_GET(info) ? TIOCM_CAR : 0)
                | (!E100_CTS_GET(info) ? TIOCM_CTS : 0);
 
-       unlock_kernel();
+       local_irq_restore(flags);
 
 #ifdef SERIAL_DEBUG_IO
        printk(KERN_DEBUG "ser%i: modem state: %i 0x%08X\n",
@@ -3702,10 +3705,6 @@ rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        struct e100_serial *info = (struct e100_serial *)tty->driver_data;
 
-       if (tty->termios->c_cflag == old_termios->c_cflag &&
-           tty->termios->c_iflag == old_termios->c_iflag)
-               return;
-
        change_speed(info);
 
        /* Handle turning off CRTSCTS */
@@ -3808,10 +3807,8 @@ rs_close(struct tty_struct *tty, struct file * filp)
 #endif
 
        shutdown(info);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
-       if (tty->ldisc.flush_buffer)
-               tty->ldisc.flush_buffer(tty);
+       rs_flush_buffer(tty);
+       tty_ldisc_flush_buffer(tty);
        tty->closing = 0;
        info->event = 0;
        info->tty = 0;
@@ -3885,6 +3882,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
         * Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO
         * R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k)
         */
+       lock_kernel();
        orig_jiffies = jiffies;
        while (info->xmit.head != info->xmit.tail || /* More in send queue */
               (*info->ostatusadr & 0x007f) ||  /* more in FIFO */
@@ -3901,6 +3899,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
                        curr_time_usec - info->last_tx_active_usec;
        }
        set_current_state(TASK_RUNNING);
+       unlock_kernel();
 }
 
 /*
@@ -4520,7 +4519,7 @@ rs_init(void)
 
        if (request_irq(SERIAL_IRQ_NBR, ser_interrupt,
                        IRQF_SHARED | IRQF_DISABLED, "serial ", driver))
-               panic("%s: Failed to request irq8", __FUNCTION__);
+               panic("%s: Failed to request irq8", __func__);
 
 #endif
 #endif /* CONFIG_SVINTO_SIM */
index 168073f12cec94b9b39b4684bb6f0e37a7e78c0a..4f1af71e9a1b2e6e0a26e44416fbb996ac4fe597 100644 (file)
@@ -52,7 +52,7 @@ static unsigned int Submodule_slot;
 #define DPRINT_CONFIG(_x...)   ;
 //#define DPRINT_CONFIG(_x...)  printk _x
 #define NOT_PROGRESS() ;
-//#define NOT_PROGRESS()       printk("%s : fails %d\n", __FUNCTION__, __LINE__)
+//#define NOT_PROGRESS()       printk("%s : fails %d\n", __func__, __LINE__)
 
 /* number of characters we want to transmit to the lower level at a time */
 #define MAX_CHARS              256
@@ -445,7 +445,7 @@ static int inline port_init(struct ioc3_port *port)
                sbbr_h = &idd->vma->sbbr_h;
                ring_pci_addr = (unsigned long __iomem)port->ip_dma_ringbuf;
                DPRINT_CONFIG(("%s: ring_pci_addr 0x%p\n",
-                              __FUNCTION__, (void *)ring_pci_addr));
+                              __func__, (void *)ring_pci_addr));
 
                writel((unsigned int)((uint64_t) ring_pci_addr >> 32), sbbr_h);
                writel((unsigned int)ring_pci_addr | BUF_SIZE_BIT, sbbr_l);
@@ -593,7 +593,7 @@ config_port(struct ioc3_port *port,
 
        DPRINT_CONFIG(("%s: line %d baud %d byte_size %d stop %d parenb %d "
                        "parodd %d\n",
-                      __FUNCTION__, ((struct uart_port *)port->ip_port)->line,
+                      __func__, ((struct uart_port *)port->ip_port)->line,
                        baud, byte_size, stop_bits, parenb, parodd));
 
        if (set_baud(port, baud))
@@ -871,14 +871,14 @@ static int ioc3_set_proto(struct ioc3_port *port, int proto)
        default:
        case PROTO_RS232:
                /* Clear the appropriate GIO pin */
-               DPRINT_CONFIG(("%s: rs232\n", __FUNCTION__));
+               DPRINT_CONFIG(("%s: rs232\n", __func__));
                writel(0, (&port->ip_idd->vma->gppr[0]
                                        + hooks->rs422_select_pin));
                break;
 
        case PROTO_RS422:
                /* Set the appropriate GIO pin */
-               DPRINT_CONFIG(("%s: rs422\n", __FUNCTION__));
+               DPRINT_CONFIG(("%s: rs422\n", __func__));
                writel(1, (&port->ip_idd->vma->gppr[0]
                                        + hooks->rs422_select_pin));
                break;
@@ -988,7 +988,7 @@ ioc3_change_speed(struct uart_port *the_port,
        }
        baud = uart_get_baud_rate(the_port, new_termios, old_termios,
                                  MIN_BAUD_SUPPORTED, MAX_BAUD_SUPPORTED);
-       DPRINT_CONFIG(("%s: returned baud %d for line %d\n", __FUNCTION__, baud,
+       DPRINT_CONFIG(("%s: returned baud %d for line %d\n", __func__, baud,
                                the_port->line));
 
        if (!the_port->fifosize)
@@ -1026,7 +1026,7 @@ ioc3_change_speed(struct uart_port *the_port,
        DPRINT_CONFIG(("%s : port 0x%p line %d cflag 0%o "
                       "config_port(baud %d data %d stop %d penable %d "
                        " parity %d), notification 0x%x\n",
-                      __FUNCTION__, (void *)port, the_port->line, cflag, baud,
+                      __func__, (void *)port, the_port->line, cflag, baud,
                       new_data, new_stop, new_parity_enable, new_parity,
                       the_port->ignore_status_mask));
 
@@ -1919,7 +1919,7 @@ static inline int ioc3_serial_core_attach( struct ioc3_submodule *is,
        struct pci_dev *pdev = idd->pdev;
 
        DPRINT_CONFIG(("%s: attach pdev 0x%p - card_ptr 0x%p\n",
-                      __FUNCTION__, pdev, (void *)card_ptr));
+                      __func__, pdev, (void *)card_ptr));
 
        if (!card_ptr)
                return -ENODEV;
@@ -1933,7 +1933,7 @@ static inline int ioc3_serial_core_attach( struct ioc3_submodule *is,
                port->ip_port = the_port;
 
                DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p [%d/%d]\n",
-                       __FUNCTION__, (void *)the_port, (void *)port,
+                       __func__, (void *)the_port, (void *)port,
                                phys_port, ii));
 
                /* membase, iobase and mapbase just need to be non-0 */
@@ -1950,7 +1950,7 @@ static inline int ioc3_serial_core_attach( struct ioc3_submodule *is,
                if (uart_add_one_port(&ioc3_uart, the_port) < 0) {
                        printk(KERN_WARNING
                          "%s: unable to add port %d bus %d\n",
-                              __FUNCTION__, the_port->line, pdev->bus->number);
+                              __func__, the_port->line, pdev->bus->number);
                } else {
                        DPRINT_CONFIG(("IOC3 serial port %d irq %d bus %d\n",
                          the_port->line, the_port->irq, pdev->bus->number));
@@ -2017,7 +2017,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
        struct ioc3_port *ports[PORTS_PER_CARD];
        int phys_port;
 
-       DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, is, idd));
+       DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __func__, is, idd));
 
        card_ptr = kzalloc(sizeof(struct ioc3_card), GFP_KERNEL);
        if (!card_ptr) {
@@ -2067,7 +2067,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
 
                        DPRINT_CONFIG(("%s : Port A ip_serial_regs 0x%p "
                                       "ip_uart_regs 0x%p\n",
-                                      __FUNCTION__,
+                                      __func__,
                                       (void *)port->ip_serial_regs,
                                       (void *)port->ip_uart_regs));
 
@@ -2082,7 +2082,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
                        DPRINT_CONFIG(("%s : Port A ip_cpu_ringbuf 0x%p "
                                       "ip_dma_ringbuf 0x%p, ip_inring 0x%p "
                                        "ip_outring 0x%p\n",
-                                      __FUNCTION__,
+                                      __func__,
                                       (void *)port->ip_cpu_ringbuf,
                                       (void *)port->ip_dma_ringbuf,
                                       (void *)port->ip_inring,
@@ -2094,7 +2094,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
 
                        DPRINT_CONFIG(("%s : Port B ip_serial_regs 0x%p "
                                       "ip_uart_regs 0x%p\n",
-                                      __FUNCTION__,
+                                      __func__,
                                       (void *)port->ip_serial_regs,
                                       (void *)port->ip_uart_regs));
 
@@ -2108,7 +2108,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
                        DPRINT_CONFIG(("%s : Port B ip_cpu_ringbuf 0x%p "
                                       "ip_dma_ringbuf 0x%p, ip_inring 0x%p "
                                        "ip_outring 0x%p\n",
-                                      __FUNCTION__,
+                                      __func__,
                                       (void *)port->ip_cpu_ringbuf,
                                       (void *)port->ip_dma_ringbuf,
                                       (void *)port->ip_inring,
@@ -2116,7 +2116,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
                }
 
                DPRINT_CONFIG(("%s : port %d [addr 0x%p] card_ptr 0x%p",
-                              __FUNCTION__,
+                              __func__,
                               phys_port, (void *)port, (void *)card_ptr));
                DPRINT_CONFIG((" ip_serial_regs 0x%p ip_uart_regs 0x%p\n",
                               (void *)port->ip_serial_regs,
@@ -2127,7 +2127,7 @@ ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
 
                DPRINT_CONFIG(("%s: phys_port %d port 0x%p inring 0x%p "
                               "outring 0x%p\n",
-                              __FUNCTION__,
+                              __func__,
                               phys_port, (void *)port,
                               (void *)port->ip_inring,
                               (void *)port->ip_outring));
@@ -2170,7 +2170,7 @@ static int __devinit ioc3uart_init(void)
        if ((ret = uart_register_driver(&ioc3_uart)) < 0) {
                printk(KERN_WARNING
                       "%s: Couldn't register IOC3 uart serial driver\n",
-                      __FUNCTION__);
+                      __func__);
                return ret;
        }
        ret = ioc3_register_submodule(&ioc3uart_submodule);
index 0c179384fb0cae34049bda432e8f349a910d3694..49b8a82b7b9f65956c96493aa6e2fd22f80d0632 100644 (file)
@@ -889,7 +889,7 @@ static int inline port_init(struct ioc4_port *port)
 
                ring_pci_addr = (unsigned long __iomem)port->ip_dma_ringbuf;
                DPRINT_CONFIG(("%s: ring_pci_addr 0x%lx\n",
-                                       __FUNCTION__, ring_pci_addr));
+                                       __func__, ring_pci_addr));
 
                writel((unsigned int)((uint64_t)ring_pci_addr >> 32), sbbr_h);
                writel((unsigned int)ring_pci_addr | IOC4_BUF_SIZE_BIT, sbbr_l);
@@ -1028,7 +1028,7 @@ static irqreturn_t ioc4_intr(int irq, void *arg)
                spin_lock_irqsave(&soft->is_ir_lock, flag);
                printk ("%s : %d : mem 0x%p sio_ir 0x%x sio_ies 0x%x "
                                "other_ir 0x%x other_ies 0x%x mask 0x%x\n",
-                    __FUNCTION__, __LINE__,
+                    __func__, __LINE__,
                     (void *)mem, readl(&mem->sio_ir.raw),
                     readl(&mem->sio_ies.raw),
                     readl(&mem->other_ir.raw),
@@ -1155,14 +1155,14 @@ static int inline ioc4_attach_local(struct ioc4_driver_data *idd)
                                (TOTAL_RING_BUF_SIZE - 1)) == 0));
                        DPRINT_CONFIG(("%s : ip_cpu_ringbuf 0x%p "
                                                "ip_dma_ringbuf 0x%p\n",
-                                       __FUNCTION__,
+                                       __func__,
                                        (void *)port->ip_cpu_ringbuf,
                                        (void *)port->ip_dma_ringbuf));
                        port->ip_inring = RING(port, RX_0_OR_2);
                        port->ip_outring = RING(port, TX_0_OR_2);
                }
                DPRINT_CONFIG(("%s : port %d [addr 0x%p] control 0x%p",
-                               __FUNCTION__,
+                               __func__,
                                port_number, (void *)port, (void *)control));
                DPRINT_CONFIG((" ip_serial_regs 0x%p ip_uart_regs 0x%p\n",
                                (void *)port->ip_serial_regs,
@@ -1173,7 +1173,7 @@ static int inline ioc4_attach_local(struct ioc4_driver_data *idd)
 
                DPRINT_CONFIG(("%s: port_number %d port 0x%p inring 0x%p "
                                                "outring 0x%p\n",
-                               __FUNCTION__,
+                               __func__,
                                port_number, (void *)port,
                                (void *)port->ip_inring,
                                (void *)port->ip_outring));
@@ -1317,7 +1317,7 @@ config_port(struct ioc4_port *port,
        int spiniter = 0;
 
        DPRINT_CONFIG(("%s: baud %d byte_size %d stop %d parenb %d parodd %d\n",
-               __FUNCTION__, baud, byte_size, stop_bits, parenb, parodd));
+               __func__, baud, byte_size, stop_bits, parenb, parodd));
 
        if (set_baud(port, baud))
                return 1;
@@ -1725,7 +1725,7 @@ ioc4_change_speed(struct uart_port *the_port,
        }
        baud = uart_get_baud_rate(the_port, new_termios, old_termios,
                                MIN_BAUD_SUPPORTED, MAX_BAUD_SUPPORTED);
-       DPRINT_CONFIG(("%s: returned baud %d\n", __FUNCTION__, baud));
+       DPRINT_CONFIG(("%s: returned baud %d\n", __func__, baud));
 
        /* default is 9600 */
        if (!baud)
@@ -1765,7 +1765,7 @@ ioc4_change_speed(struct uart_port *the_port,
        DPRINT_CONFIG(("%s : port 0x%p cflag 0%o "
                "config_port(baud %d data %d stop %d p enable %d parity %d),"
                " notification 0x%x\n",
-            __FUNCTION__, (void *)port, cflag, baud, new_data, new_stop,
+            __func__, (void *)port, cflag, baud, new_data, new_stop,
             new_parity_enable, new_parity, the_port->ignore_status_mask));
 
        if ((config_port(port, baud,            /* baud */
@@ -2715,7 +2715,7 @@ ioc4_serial_core_attach(struct pci_dev *pdev, int port_type)
 
 
        DPRINT_CONFIG(("%s: attach pdev 0x%p - control 0x%p\n",
-                       __FUNCTION__, pdev, (void *)control));
+                       __func__, pdev, (void *)control));
 
        if (!control)
                return -ENODEV;
@@ -2734,7 +2734,7 @@ ioc4_serial_core_attach(struct pci_dev *pdev, int port_type)
                port->ip_all_ports[port_type_idx] = the_port;
 
                DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p : type %s\n",
-                               __FUNCTION__, (void *)the_port,
+                               __func__, (void *)the_port,
                                (void *)port,
                                port_type == PROTO_RS232 ? "rs232" : "rs422"));
 
@@ -2752,7 +2752,7 @@ ioc4_serial_core_attach(struct pci_dev *pdev, int port_type)
                if (uart_add_one_port(u_driver, the_port) < 0) {
                        printk(KERN_WARNING
                           "%s: unable to add port %d bus %d\n",
-                              __FUNCTION__, the_port->line, pdev->bus->number);
+                              __func__, the_port->line, pdev->bus->number);
                } else {
                        DPRINT_CONFIG(
                            ("IOC4 serial port %d irq = %d, bus %d\n",
@@ -2777,7 +2777,7 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd)
        int ret = 0;
 
 
-       DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, idd->idd_pdev,
+       DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __func__, idd->idd_pdev,
                                                        idd->idd_pci_id));
 
        /* PCI-RT does not bring out serial connections.
@@ -2806,7 +2806,7 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd)
                goto out2;
        }
        DPRINT_CONFIG(("%s : mem 0x%p, serial 0x%p\n",
-                               __FUNCTION__, (void *)idd->idd_misc_regs,
+                               __func__, (void *)idd->idd_misc_regs,
                                (void *)serial));
 
        /* Get memory for the new card */
@@ -2858,7 +2858,7 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd)
        } else {
                printk(KERN_WARNING
                    "%s : request_irq fails for IRQ 0x%x\n ",
-                       __FUNCTION__, idd->idd_pdev->irq);
+                       __func__, idd->idd_pdev->irq);
        }
        ret = ioc4_attach_local(idd);
        if (ret)
@@ -2911,13 +2911,13 @@ int ioc4_serial_init(void)
        if ((ret = uart_register_driver(&ioc4_uart_rs232)) < 0) {
                printk(KERN_WARNING
                        "%s: Couldn't register rs232 IOC4 serial driver\n",
-                       __FUNCTION__);
+                       __func__);
                return ret;
        }
        if ((ret = uart_register_driver(&ioc4_uart_rs422)) < 0) {
                printk(KERN_WARNING
                        "%s: Couldn't register rs422 IOC4 serial driver\n",
-                       __FUNCTION__);
+                       __func__);
                return ret;
        }
 
index 9cf03327386acce3b382b7d63c579546b5ff0dd4..eadc1ab6bbcead8918a19773a7db2f08d85ec0a3 100644 (file)
@@ -96,12 +96,14 @@ static void cleanup_kgdboc(void)
 
 static int kgdboc_get_char(void)
 {
-       return kgdb_tty_driver->poll_get_char(kgdb_tty_driver, kgdb_tty_line);
+       return kgdb_tty_driver->ops->poll_get_char(kgdb_tty_driver,
+                                               kgdb_tty_line);
 }
 
 static void kgdboc_put_char(u8 chr)
 {
-       kgdb_tty_driver->poll_put_char(kgdb_tty_driver, kgdb_tty_line, chr);
+       kgdb_tty_driver->ops->poll_put_char(kgdb_tty_driver,
+                                       kgdb_tty_line, chr);
 }
 
 static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp)
index ddd3aa50d4adef5de5e136df8fbd5fa3a8738ad8..43af40d59b8af44717621150e13194afd85efdff 100644 (file)
@@ -1072,18 +1072,6 @@ static int mcfrs_ioctl(struct tty_struct *tty, struct file * file,
                        tty_wait_until_sent(tty, 0);
                        send_break(info, arg ? arg*(HZ/10) : HZ/4);
                        return 0;
-               case TIOCGSOFTCAR:
-                       error = put_user(C_CLOCAL(tty) ? 1 : 0,
-                                   (unsigned long *) arg);
-                       if (error)
-                               return error;
-                       return 0;
-               case TIOCSSOFTCAR:
-                       get_user(arg, (unsigned long *) arg);
-                       tty->termios->c_cflag =
-                               ((tty->termios->c_cflag & ~CLOCAL) |
-                                (arg ? CLOCAL : 0));
-                       return 0;
                case TIOCGSERIAL:
                        if (access_ok(VERIFY_WRITE, (void *) arg,
                                                sizeof(struct serial_struct)))
@@ -1222,8 +1210,7 @@ static void mcfrs_close(struct tty_struct *tty, struct file * filp)
        } else
 #endif
        shutdown(info);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       mcfrs_flush_buffer(tty);
        tty_ldisc_flush(tty);
        
        tty->closing = 0;
@@ -1276,6 +1263,8 @@ mcfrs_wait_until_sent(struct tty_struct *tty, int timeout)
         * Note: we have to use pretty tight timings here to satisfy
         * the NIST-PCTS.
         */
+       lock_kernel();
+
        fifo_time = (MCF5272_FIFO_SIZE * HZ * 10) / info->baud;
        char_time = fifo_time / 5;
        if (char_time == 0)
@@ -1312,6 +1301,7 @@ mcfrs_wait_until_sent(struct tty_struct *tty, int timeout)
                if (timeout && time_after(jiffies, orig_jiffies + timeout))
                        break;
        }
+       unlock_kernel();
 #else
        /*
         * For the other coldfire models, assume all data has been sent
@@ -1907,7 +1897,7 @@ static struct tty_driver *mcfrs_console_device(struct console *c, int *index)
  *     This is used for console output.
  */
 
-void mcfrs_put_char(char ch)
+int mcfrs_put_char(char ch)
 {
        volatile unsigned char  *uartp;
        unsigned long           flags;
@@ -1931,7 +1921,7 @@ void mcfrs_put_char(char ch)
                mcfrs_init_console(); /* try and get it back */
        local_irq_restore(flags);
 
-       return;
+       return 1;
 }
 
 
index 3123ffeac8ad682e4ec383cd9d9606bc095270fe..81ac9bb4f39b74a7a9e1b2456ae6484a49a0f560 100644 (file)
@@ -287,6 +287,7 @@ static void netx_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
        unsigned int val;
 
+       /* FIXME: Locking needed ? */
        if (mctrl & TIOCM_RTS) {
                val = readl(port->membase + UART_RTS_CR);
                writel(val | RTS_CR_RTS, port->membase + UART_RTS_CR);
index 4ffa2585429a4965d979b67cea2ba870357baef5..2b6a013639e6db103656787fb567f168e8e802b3 100644 (file)
@@ -1022,6 +1022,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
        struct uart_port *port = &ourport->port;
        struct s3c2410_uartcfg *cfg;
        struct resource *res;
+       int ret;
 
        dbg("s3c24xx_serial_init_port: port=%p, platdev=%p\n", port, platdev);
 
@@ -1064,9 +1065,11 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
 
        port->mapbase   = res->start;
        port->membase   = S3C24XX_VA_UART + (res->start - S3C24XX_PA_UART);
-       port->irq       = platform_get_irq(platdev, 0);
-       if (port->irq < 0)
+       ret = platform_get_irq(platdev, 0);
+       if (ret < 0)
                port->irq = 0;
+       else
+               port->irq = ret;
 
        ourport->clk    = clk_get(&platdev->dev, "uart");
 
@@ -1093,13 +1096,13 @@ static int s3c24xx_serial_probe(struct platform_device *dev,
        ourport = &s3c24xx_serial_ports[probe_index];
        probe_index++;
 
-       dbg("%s: initialising port %p...\n", __FUNCTION__, ourport);
+       dbg("%s: initialising port %p...\n", __func__, ourport);
 
        ret = s3c24xx_serial_init_port(ourport, info, dev);
        if (ret < 0)
                goto probe_err;
 
-       dbg("%s: adding port\n", __FUNCTION__);
+       dbg("%s: adding port\n", __func__);
        uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
        platform_set_drvdata(dev, &ourport->port);
 
@@ -1584,7 +1587,7 @@ static int s3c2412_serial_resetport(struct uart_port *port,
        unsigned long ucon = rd_regl(port, S3C2410_UCON);
 
        dbg("%s: port=%p (%08lx), cfg=%p\n",
-           __FUNCTION__, port, port->mapbase, cfg);
+           __func__, port, port->mapbase, cfg);
 
        /* ensure we don't change the clock settings... */
 
index 67b2338913c2d08c7fd58a86836053b899cfbf0d..62b38582f5e940588d29e0dd8108c0dcf1c0d34f 100644 (file)
@@ -655,7 +655,7 @@ void __init sa1100_register_uart_fns(struct sa1100_port_fns *fns)
 void __init sa1100_register_uart(int idx, int port)
 {
        if (idx >= NR_PORTS) {
-               printk(KERN_ERR "%s: bad index number %d\n", __FUNCTION__, idx);
+               printk(KERN_ERR "%s: bad index number %d\n", __func__, idx);
                return;
        }
 
@@ -682,7 +682,7 @@ void __init sa1100_register_uart(int idx, int port)
                break;
 
        default:
-               printk(KERN_ERR "%s: bad port number %d\n", __FUNCTION__, port);
+               printk(KERN_ERR "%s: bad port number %d\n", __func__, port);
        }
 }
 
index 977ce820ce303914dc7e998940cdf524dec52586..1e2b9d826f69a5db2756e8eb477f2249587122e4 100644 (file)
@@ -422,6 +422,7 @@ uart_get_divisor(struct uart_port *port, unsigned int baud)
 
 EXPORT_SYMBOL(uart_get_divisor);
 
+/* FIXME: Consistent locking policy */
 static void
 uart_change_speed(struct uart_state *state, struct ktermios *old_termios)
 {
@@ -454,27 +455,30 @@ uart_change_speed(struct uart_state *state, struct ktermios *old_termios)
        port->ops->set_termios(port, termios, old_termios);
 }
 
-static inline void
+static inline int
 __uart_put_char(struct uart_port *port, struct circ_buf *circ, unsigned char c)
 {
        unsigned long flags;
+       int ret = 0;
 
        if (!circ->buf)
-               return;
+               return 0;
 
        spin_lock_irqsave(&port->lock, flags);
        if (uart_circ_chars_free(circ) != 0) {
                circ->buf[circ->head] = c;
                circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
+               ret = 1;
        }
        spin_unlock_irqrestore(&port->lock, flags);
+       return ret;
 }
 
-static void uart_put_char(struct tty_struct *tty, unsigned char ch)
+static int uart_put_char(struct tty_struct *tty, unsigned char ch)
 {
        struct uart_state *state = tty->driver_data;
 
-       __uart_put_char(state->port, &state->info->xmit, ch);
+       return __uart_put_char(state->port, &state->info->xmit, ch);
 }
 
 static void uart_flush_chars(struct tty_struct *tty)
@@ -528,15 +532,25 @@ uart_write(struct tty_struct *tty, const unsigned char *buf, int count)
 static int uart_write_room(struct tty_struct *tty)
 {
        struct uart_state *state = tty->driver_data;
+       unsigned long flags;
+       int ret;
 
-       return uart_circ_chars_free(&state->info->xmit);
+       spin_lock_irqsave(&state->port->lock, flags);
+       ret = uart_circ_chars_free(&state->info->xmit);
+       spin_unlock_irqrestore(&state->port->lock, flags);
+       return ret;
 }
 
 static int uart_chars_in_buffer(struct tty_struct *tty)
 {
        struct uart_state *state = tty->driver_data;
+       unsigned long flags;
+       int ret;
 
-       return uart_circ_chars_pending(&state->info->xmit);
+       spin_lock_irqsave(&state->port->lock, flags);
+       ret = uart_circ_chars_pending(&state->info->xmit);
+       spin_unlock_irqrestore(&state->port->lock, flags);
+       return ret;
 }
 
 static void uart_flush_buffer(struct tty_struct *tty)
@@ -618,6 +632,11 @@ static int uart_get_info(struct uart_state *state,
        struct serial_struct tmp;
 
        memset(&tmp, 0, sizeof(tmp));
+
+       /* Ensure the state we copy is consistent and no hardware changes
+          occur as we go */
+       mutex_lock(&state->mutex);
+
        tmp.type            = port->type;
        tmp.line            = port->line;
        tmp.port            = port->iobase;
@@ -637,6 +656,8 @@ static int uart_get_info(struct uart_state *state,
        tmp.iomem_reg_shift = port->regshift;
        tmp.iomem_base      = (void *)(unsigned long)port->mapbase;
 
+       mutex_unlock(&state->mutex);
+
        if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
                return -EFAULT;
        return 0;
@@ -914,8 +935,6 @@ static void uart_break_ctl(struct tty_struct *tty, int break_state)
        struct uart_state *state = tty->driver_data;
        struct uart_port *port = state->port;
 
-       BUG_ON(!kernel_locked());
-
        mutex_lock(&state->mutex);
 
        if (port->type != PORT_UNKNOWN)
@@ -1059,7 +1078,7 @@ static int uart_get_count(struct uart_state *state,
 }
 
 /*
- * Called via sys_ioctl under the BKL.  We can use spin_lock_irq() here.
+ * Called via sys_ioctl.  We can use spin_lock_irq() here.
  */
 static int
 uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
@@ -1069,7 +1088,6 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
        void __user *uarg = (void __user *)arg;
        int ret = -ENOIOCTLCMD;
 
-       BUG_ON(!kernel_locked());
 
        /*
         * These ioctls don't rely on the hardware to be present.
@@ -1140,9 +1158,9 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
                break;
        }
        }
- out_up:
+out_up:
        mutex_unlock(&state->mutex);
- out:
+out:
        return ret;
 }
 
@@ -1153,7 +1171,6 @@ static void uart_set_termios(struct tty_struct *tty,
        unsigned long flags;
        unsigned int cflag = tty->termios->c_cflag;
 
-       BUG_ON(!kernel_locked());
 
        /*
         * These are the bits that are used to setup various
@@ -1165,8 +1182,9 @@ static void uart_set_termios(struct tty_struct *tty,
        if ((cflag ^ old_termios->c_cflag) == 0 &&
            tty->termios->c_ospeed == old_termios->c_ospeed &&
            tty->termios->c_ispeed == old_termios->c_ispeed &&
-           RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0)
+           RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0) {
                return;
+       }
 
        uart_change_speed(state, old_termios);
 
@@ -1200,7 +1218,6 @@ static void uart_set_termios(struct tty_struct *tty,
                }
                spin_unlock_irqrestore(&state->port->lock, flags);
        }
-
 #if 0
        /*
         * No need to wake up processes in open wait, since they
@@ -1316,11 +1333,11 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
        struct uart_port *port = state->port;
        unsigned long char_time, expire;
 
-       BUG_ON(!kernel_locked());
-
        if (port->type == PORT_UNKNOWN || port->fifosize == 0)
                return;
 
+       lock_kernel();
+
        /*
         * Set the check interval to be 1/5 of the estimated time to
         * send a single character, and make it at least 1.  The check
@@ -1366,6 +1383,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
                        break;
        }
        set_current_state(TASK_RUNNING); /* might not be needed */
+       unlock_kernel();
 }
 
 /*
@@ -2079,7 +2097,9 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
                int ret;
 
                uart_change_pm(state, 0);
+               spin_lock_irq(&port->lock);
                ops->set_mctrl(port, 0);
+               spin_unlock_irq(&port->lock);
                ret = ops->startup(port);
                if (ret == 0) {
                        uart_change_speed(state, NULL);
index c2ea5d4df44a07c5aab6ae01bb86b9a73cade4d0..969106187718d909e0aacb9478477296d43e04ae 100644 (file)
@@ -855,7 +855,7 @@ static int sci_notifier(struct notifier_block *self,
 
                printk(KERN_INFO "%s: got a postchange notification "
                       "for cpu %d (old %d, new %d)\n",
-                      __FUNCTION__, freqs->cpu, freqs->old, freqs->new);
+                      __func__, freqs->cpu, freqs->old, freqs->new);
        }
 
        return NOTIFY_OK;
index 41fc61264443578e77fc4deb16ef276c79d2d502..019da2e05f0b4825d41ada3cf6e6badc609b8885 100644 (file)
@@ -839,7 +839,7 @@ static int __init sn_sal_module_init(void)
 
        if (uart_add_one_port(&sal_console_uart, &sal_console_port.sc_port) < 0) {
                /* error - not sure what I'd do - so I'll do nothing */
-               printk(KERN_ERR "%s: unable to add port\n", __FUNCTION__);
+               printk(KERN_ERR "%s: unable to add port\n", __func__);
        }
 
        /* when this driver is compiled in, the console initialization
index b565d5a37499799ac3e9873a757fb1b7dc5d1df5..b51c24245be4e361d05c0bf545760375806d0a3a 100644 (file)
@@ -584,7 +584,7 @@ ulite_of_probe(struct of_device *op, const struct of_device_id *match)
        const unsigned int *id;
        int irq, rc;
 
-       dev_dbg(&op->dev, "%s(%p, %p)\n", __FUNCTION__, op, match);
+       dev_dbg(&op->dev, "%s(%p, %p)\n", __func__, op, match);
 
        rc = of_address_to_resource(op->node, 0, &res);
        if (rc) {
index 5e4310ccd5914ecc26983a8ad51bc3bd5fd61624..01917c433f17939000324e82abe63edeb0a72f15 100644 (file)
@@ -215,7 +215,7 @@ static inline dma_addr_t cpu2qe_addr(void *addr, struct uart_qe_port *qe_port)
                return qe_port->bd_dma_addr + (addr - qe_port->bd_virt);
 
        /* something nasty happened */
-       printk(KERN_ERR "%s: addr=%p\n", __FUNCTION__, addr);
+       printk(KERN_ERR "%s: addr=%p\n", __func__, addr);
        BUG();
        return 0;
 }
@@ -234,7 +234,7 @@ static inline void *qe2cpu_addr(dma_addr_t addr, struct uart_qe_port *qe_port)
                return qe_port->bd_virt + (addr - qe_port->bd_dma_addr);
 
        /* something nasty happened */
-       printk(KERN_ERR "%s: addr=%x\n", __FUNCTION__, addr);
+       printk(KERN_ERR "%s: addr=%x\n", __func__, addr);
        BUG();
        return NULL;
 }
index 02c8e305b14fd783e3b94a71d3c8b4d9c4ed9c68..e81d59d789108041fee33e62b22b82d14e34fef3 100644 (file)
@@ -497,7 +497,7 @@ static int atmel_spi_setup(struct spi_device *spi)
        struct atmel_spi        *as;
        u32                     scbr, csr;
        unsigned int            bits = spi->bits_per_word;
-       unsigned long           bus_hz, sck_hz;
+       unsigned long           bus_hz;
        unsigned int            npcs_pin;
        int                     ret;
 
@@ -536,14 +536,25 @@ static int atmel_spi_setup(struct spi_device *spi)
                return -EINVAL;
        }
 
-       /* speed zero convention is used by some upper layers */
+       /*
+        * Pre-new_1 chips start out at half the peripheral
+        * bus speed.
+        */
        bus_hz = clk_get_rate(as->clk);
+       if (!as->new_1)
+               bus_hz /= 2;
+
        if (spi->max_speed_hz) {
-               /* assume div32/fdiv/mbz == 0 */
-               if (!as->new_1)
-                       bus_hz /= 2;
-               scbr = ((bus_hz + spi->max_speed_hz - 1)
-                       / spi->max_speed_hz);
+               /*
+                * Calculate the lowest divider that satisfies the
+                * constraint, assuming div32/fdiv/mbz == 0.
+                */
+               scbr = DIV_ROUND_UP(bus_hz, spi->max_speed_hz);
+
+               /*
+                * If the resulting divider doesn't fit into the
+                * register bitfield, we can't satisfy the constraint.
+                */
                if (scbr >= (1 << SPI_SCBR_SIZE)) {
                        dev_dbg(&spi->dev,
                                "setup: %d Hz too slow, scbr %u; min %ld Hz\n",
@@ -551,8 +562,8 @@ static int atmel_spi_setup(struct spi_device *spi)
                        return -EINVAL;
                }
        } else
+               /* speed zero means "as slow as possible" */
                scbr = 0xff;
-       sck_hz = bus_hz / scbr;
 
        csr = SPI_BF(SCBR, scbr) | SPI_BF(BITS, bits - 8);
        if (spi->mode & SPI_CPOL)
@@ -589,7 +600,7 @@ static int atmel_spi_setup(struct spi_device *spi)
 
        dev_dbg(&spi->dev,
                "setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n",
-               sck_hz, bits, spi->mode, spi->chip_select, csr);
+               bus_hz / scbr, bits, spi->mode, spi->chip_select, csr);
 
        spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
 
index 4220f22b66603f9f285915dc659bb73ce8ff9abb..5f71ff3aee35f01203e36b3344f2d7dec3d1f40a 100644 (file)
@@ -305,8 +305,6 @@ enum {
  */
 
 #define FW_GET_BYTE(p) *((__u8 *) (p))
-#define FW_GET_WORD(p) le16_to_cpu(get_unaligned((__le16 *) (p)))
-#define FW_GET_LONG(p) le32_to_cpu(get_unaligned((__le32 *) (p)))
 
 #define FW_DIR "ueagle-atm/"
 #define NB_MODEM 4
@@ -621,7 +619,7 @@ static void uea_upload_pre_firmware(const struct firmware *fw_entry, void *conte
        if (size < 4)
                goto err_fw_corrupted;
 
-       crc = FW_GET_LONG(pfw);
+       crc = get_unaligned_le32(pfw);
        pfw += 4;
        size -= 4;
        if (crc32_be(0, pfw, size) != crc)
@@ -640,7 +638,7 @@ static void uea_upload_pre_firmware(const struct firmware *fw_entry, void *conte
 
        while (size > 3) {
                u8 len = FW_GET_BYTE(pfw);
-               u16 add = FW_GET_WORD(pfw + 1);
+               u16 add = get_unaligned_le16(pfw + 1);
 
                size -= len + 3;
                if (size < 0)
@@ -738,7 +736,7 @@ static int check_dsp_e1(u8 *dsp, unsigned int len)
 
        for (i = 0; i < pagecount; i++) {
 
-               pageoffset = FW_GET_LONG(dsp + p);
+               pageoffset = get_unaligned_le32(dsp + p);
                p += 4;
 
                if (pageoffset == 0)
@@ -759,7 +757,7 @@ static int check_dsp_e1(u8 *dsp, unsigned int len)
                                return 1;
 
                        pp += 2;        /* skip blockaddr */
-                       blocksize = FW_GET_WORD(dsp + pp);
+                       blocksize = get_unaligned_le16(dsp + pp);
                        pp += 2;
 
                        /* enough space for block data? */
@@ -928,7 +926,7 @@ static void uea_load_page_e1(struct work_struct *work)
                goto bad1;
 
        p += 4 * pageno;
-       pageoffset = FW_GET_LONG(p);
+       pageoffset = get_unaligned_le32(p);
 
        if (pageoffset == 0)
                goto bad1;
@@ -945,10 +943,10 @@ static void uea_load_page_e1(struct work_struct *work)
        bi.wOvlOffset = cpu_to_le16(ovl | 0x8000);
 
        for (i = 0; i < blockcount; i++) {
-               blockaddr = FW_GET_WORD(p);
+               blockaddr = get_unaligned_le16(p);
                p += 2;
 
-               blocksize = FW_GET_WORD(p);
+               blocksize = get_unaligned_le16(p);
                p += 2;
 
                bi.wSize = cpu_to_le16(blocksize);
@@ -1152,9 +1150,9 @@ static int uea_cmv_e1(struct uea_softc *sc,
        cmv.bDirection = E1_HOSTTOMODEM;
        cmv.bFunction = function;
        cmv.wIndex = cpu_to_le16(sc->cmv_dsc.e1.idx);
-       put_unaligned(cpu_to_le32(address), &cmv.dwSymbolicAddress);
+       put_unaligned_le32(address, &cmv.dwSymbolicAddress);
        cmv.wOffsetAddress = cpu_to_le16(offset);
-       put_unaligned(cpu_to_le32(data >> 16 | data << 16), &cmv.dwData);
+       put_unaligned_le32(data >> 16 | data << 16, &cmv.dwData);
 
        ret = uea_request(sc, UEA_E1_SET_BLOCK, UEA_MPTX_START, sizeof(cmv), &cmv);
        if (ret < 0)
@@ -1646,7 +1644,7 @@ static int request_cmvs(struct uea_softc *sc,
        if (size < 5)
                goto err_fw_corrupted;
 
-       crc = FW_GET_LONG(data);
+       crc = get_unaligned_le32(data);
        data += 4;
        size -= 4;
        if (crc32_be(0, data, size) != crc)
@@ -1696,9 +1694,9 @@ static int uea_send_cmvs_e1(struct uea_softc *sc)
                        "please update your firmware\n");
 
                for (i = 0; i < len; i++) {
-                       ret = uea_write_cmv_e1(sc, FW_GET_LONG(&cmvs_v1[i].address),
-                                               FW_GET_WORD(&cmvs_v1[i].offset),
-                                               FW_GET_LONG(&cmvs_v1[i].data));
+                       ret = uea_write_cmv_e1(sc, get_unaligned_le32(&cmvs_v1[i].address),
+                                               get_unaligned_le16(&cmvs_v1[i].offset),
+                                               get_unaligned_le32(&cmvs_v1[i].data));
                        if (ret < 0)
                                goto out;
                }
@@ -1706,9 +1704,9 @@ static int uea_send_cmvs_e1(struct uea_softc *sc)
                struct uea_cmvs_v2 *cmvs_v2 = cmvs_ptr;
 
                for (i = 0; i < len; i++) {
-                       ret = uea_write_cmv_e1(sc, FW_GET_LONG(&cmvs_v2[i].address),
-                                               (u16) FW_GET_LONG(&cmvs_v2[i].offset),
-                                               FW_GET_LONG(&cmvs_v2[i].data));
+                       ret = uea_write_cmv_e1(sc, get_unaligned_le32(&cmvs_v2[i].address),
+                                               (u16) get_unaligned_le32(&cmvs_v2[i].offset),
+                                               get_unaligned_le32(&cmvs_v2[i].data));
                        if (ret < 0)
                                goto out;
                }
@@ -1759,10 +1757,10 @@ static int uea_send_cmvs_e4(struct uea_softc *sc)
 
                for (i = 0; i < len; i++) {
                        ret = uea_write_cmv_e4(sc, 1,
-                                               FW_GET_LONG(&cmvs_v2[i].group),
-                                               FW_GET_LONG(&cmvs_v2[i].address),
-                                               FW_GET_LONG(&cmvs_v2[i].offset),
-                                               FW_GET_LONG(&cmvs_v2[i].data));
+                                               get_unaligned_le32(&cmvs_v2[i].group),
+                                               get_unaligned_le32(&cmvs_v2[i].address),
+                                               get_unaligned_le32(&cmvs_v2[i].offset),
+                                               get_unaligned_le32(&cmvs_v2[i].data));
                        if (ret < 0)
                                goto out;
                }
@@ -1964,7 +1962,7 @@ static void uea_dispatch_cmv_e1(struct uea_softc *sc, struct intr_pkt *intr)
                if (UEA_CHIP_VERSION(sc) == ADI930
                                && cmv->bFunction ==  E1_MAKEFUNCTION(2, 2)) {
                        cmv->wIndex = cpu_to_le16(dsc->idx);
-                       put_unaligned(cpu_to_le32(dsc->address), &cmv->dwSymbolicAddress);
+                       put_unaligned_le32(dsc->address, &cmv->dwSymbolicAddress);
                        cmv->wOffsetAddress = cpu_to_le16(dsc->offset);
                } else
                        goto bad2;
@@ -1978,11 +1976,11 @@ static void uea_dispatch_cmv_e1(struct uea_softc *sc, struct intr_pkt *intr)
 
        /* in case of MEMACCESS */
        if (le16_to_cpu(cmv->wIndex) != dsc->idx ||
-           le32_to_cpu(get_unaligned(&cmv->dwSymbolicAddress)) != dsc->address ||
+           get_unaligned_le32(&cmv->dwSymbolicAddress) != dsc->address ||
            le16_to_cpu(cmv->wOffsetAddress) != dsc->offset)
                goto bad2;
 
-       sc->data = le32_to_cpu(get_unaligned(&cmv->dwData));
+       sc->data = get_unaligned_le32(&cmv->dwData);
        sc->data = sc->data << 16 | sc->data >> 16;
 
        wake_up_cmv_ack(sc);
index 7b572e75e73cac3046e2662d86f6521f4885db2a..cefe7f2c6f750d5ac8ab3c0483b0a535cb22c273 100644 (file)
@@ -280,7 +280,7 @@ static void acm_ctrl_irq(struct urb *urb)
 
                case USB_CDC_NOTIFY_SERIAL_STATE:
 
-                       newctrl = le16_to_cpu(get_unaligned((__le16 *) data));
+                       newctrl = get_unaligned_le16(data);
 
                        if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
                                dbg("calling hangup");
index 8607846e3c3f7bf1f2998953b61517756a3a4c14..1d253dd4ea8143040b4175286331d349a95a1e9c 100644 (file)
@@ -773,7 +773,7 @@ int __init usbfs_init(void)
        usb_register_notify(&usbfs_nb);
 
        /* create mount point for usbfs */
-       usbdir = proc_mkdir("usb", proc_bus);
+       usbdir = proc_mkdir("bus/usb", NULL);
 
        return 0;
 }
@@ -783,6 +783,6 @@ void usbfs_cleanup(void)
        usb_unregister_notify(&usbfs_nb);
        unregister_filesystem(&usb_fs_type);
        if (usbdir)
-               remove_proc_entry("usb", proc_bus);
+               remove_proc_entry("bus/usb", NULL);
 }
 
index 9b913afb2e6dab7beb727a7400516247b4863a59..274c60a970cdcf8a7f3f0409e0d1512ec653477f 100644 (file)
@@ -231,6 +231,7 @@ static int proc_udc_open(struct inode *inode, struct file *file)
 }
 
 static const struct file_operations proc_ops = {
+       .owner          = THIS_MODULE,
        .open           = proc_udc_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -239,15 +240,7 @@ static const struct file_operations proc_ops = {
 
 static void create_debug_file(struct at91_udc *udc)
 {
-       struct proc_dir_entry *pde;
-
-       pde = create_proc_entry (debug_filename, 0, NULL);
-       udc->pde = pde;
-       if (pde == NULL)
-               return;
-
-       pde->proc_fops = &proc_ops;
-       pde->data = udc;
+       udc->pde = proc_create_data(debug_filename, 0, NULL, &proc_ops, udc);
 }
 
 static void remove_debug_file(struct at91_udc *udc)
index 64a592cbbe7b7f4aa3b3236ebd165ce726cdb6cb..be6613afedbfd317f907a4d252973b4b9c73b787 100644 (file)
@@ -127,7 +127,7 @@ goku_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 
        /* enabling the no-toggle interrupt mode would need an api hook */
        mode = 0;
-       max = le16_to_cpu(get_unaligned(&desc->wMaxPacketSize));
+       max = get_unaligned_le16(&desc->wMaxPacketSize);
        switch (max) {
        case 64:        mode++;
        case 32:        mode++;
index 95f7662376f16e41e463ec3feef0c243842517f9..881d74c3d9646b482130b2afcf651ed974a97f6a 100644 (file)
@@ -2504,6 +2504,7 @@ static int proc_udc_open(struct inode *inode, struct file *file)
 }
 
 static const struct file_operations proc_ops = {
+       .owner          = THIS_MODULE,
        .open           = proc_udc_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -2512,11 +2513,7 @@ static const struct file_operations proc_ops = {
 
 static void create_proc_file(void)
 {
-       struct proc_dir_entry *pde;
-
-       pde = create_proc_entry (proc_filename, 0, NULL);
-       if (pde)
-               pde->proc_fops = &proc_ops;
+       proc_create(proc_filename, 0, NULL, &proc_ops);
 }
 
 static void remove_proc_file(void)
index bd58dd504f6f4ec144048432b51a8d8737047751..d0677f5d3cd5f3f8b88b5c73573113f7fed672d1 100644 (file)
@@ -183,14 +183,10 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                DBG("query OID %08x value, len %d:\n", OID, buf_len);
                for (i = 0; i < buf_len; i += 16) {
                        DBG("%03d: %08x %08x %08x %08x\n", i,
-                               le32_to_cpu(get_unaligned((__le32 *)
-                                       &buf[i])),
-                               le32_to_cpu(get_unaligned((__le32 *)
-                                       &buf[i + 4])),
-                               le32_to_cpu(get_unaligned((__le32 *)
-                                       &buf[i + 8])),
-                               le32_to_cpu(get_unaligned((__le32 *)
-                                       &buf[i + 12])));
+                               get_unaligned_le32(&buf[i]),
+                               get_unaligned_le32(&buf[i + 4]),
+                               get_unaligned_le32(&buf[i + 8]),
+                               get_unaligned_le32(&buf[i + 12]));
                }
        }
 
@@ -666,7 +662,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
                break;
        case OID_PNP_QUERY_POWER:
                DBG("%s: OID_PNP_QUERY_POWER D%d\n", __func__,
-                               le32_to_cpu(get_unaligned((__le32 *)buf)) - 1);
+                               get_unaligned_le32(buf) - 1);
                /* only suspend is a real power state, and
                 * it can't be entered by OID_PNP_SET_POWER...
                 */
@@ -705,14 +701,10 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
                DBG("set OID %08x value, len %d:\n", OID, buf_len);
                for (i = 0; i < buf_len; i += 16) {
                        DBG("%03d: %08x %08x %08x %08x\n", i,
-                               le32_to_cpu(get_unaligned((__le32 *)
-                                       &buf[i])),
-                               le32_to_cpu(get_unaligned((__le32 *)
-                                       &buf[i + 4])),
-                               le32_to_cpu(get_unaligned((__le32 *)
-                                       &buf[i + 8])),
-                               le32_to_cpu(get_unaligned((__le32 *)
-                                       &buf[i + 12])));
+                               get_unaligned_le32(&buf[i]),
+                               get_unaligned_le32(&buf[i + 4]),
+                               get_unaligned_le32(&buf[i + 8]),
+                               get_unaligned_le32(&buf[i + 12]));
                }
        }
 
@@ -726,8 +718,7 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
                 *      PROMISCUOUS, DIRECTED,
                 *      MULTICAST, ALL_MULTICAST, BROADCAST
                 */
-               *params->filter = (u16) le32_to_cpu(get_unaligned(
-                               (__le32 *)buf));
+               *params->filter = (u16)get_unaligned_le32(buf);
                DBG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
                        __func__, *params->filter);
 
@@ -777,7 +768,7 @@ update_linkstate:
                 * resuming, Windows forces a reset, and then SET_POWER D0.
                 * FIXME ... then things go batty; Windows wedges itself.
                 */
-               i = le32_to_cpu(get_unaligned((__le32 *)buf));
+               i = get_unaligned_le32(buf);
                DBG("%s: OID_PNP_SET_POWER D%d\n", __func__, i - 1);
                switch (i) {
                case NdisDeviceStateD0:
@@ -1064,8 +1055,8 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
                return -ENOMEM;
 
        tmp = (__le32 *) buf;
-       MsgType   = le32_to_cpu(get_unaligned(tmp++));
-       MsgLength = le32_to_cpu(get_unaligned(tmp++));
+       MsgType   = get_unaligned_le32(tmp++);
+       MsgLength = get_unaligned_le32(tmp++);
 
        if (configNr >= RNDIS_MAX_CONFIGS)
                return -ENOTSUPP;
@@ -1296,10 +1287,9 @@ int rndis_rm_hdr(struct sk_buff *skb)
        tmp++;
 
        /* DataOffset, DataLength */
-       if (!skb_pull(skb, le32_to_cpu(get_unaligned(tmp++))
-                       + 8 /* offset of DataOffset */))
+       if (!skb_pull(skb, get_unaligned_le32(tmp++) + 8))
                return -EOVERFLOW;
-       skb_trim(skb, le32_to_cpu(get_unaligned(tmp++)));
+       skb_trim(skb, get_unaligned_le32(tmp++));
 
        return 0;
 }
index 433b3f44f42e2dc36e38e2b7dc85be3e48b3785a..8d158e5640e37782ea0dbed21c08277092a2614e 100644 (file)
@@ -170,7 +170,7 @@ static int gs_open(struct tty_struct *tty, struct file *file);
 static void gs_close(struct tty_struct *tty, struct file *file);
 static int gs_write(struct tty_struct *tty,
        const unsigned char *buf, int count);
-static void gs_put_char(struct tty_struct *tty, unsigned char ch);
+static int gs_put_char(struct tty_struct *tty, unsigned char ch);
 static void gs_flush_chars(struct tty_struct *tty);
 static int gs_write_room(struct tty_struct *tty);
 static int gs_chars_in_buffer(struct tty_struct *tty);
@@ -883,14 +883,15 @@ exit:
 /*
  * gs_put_char
  */
-static void gs_put_char(struct tty_struct *tty, unsigned char ch)
+static int gs_put_char(struct tty_struct *tty, unsigned char ch)
 {
        unsigned long flags;
        struct gs_port *port = tty->driver_data;
+       int ret = 0;
 
        if (port == NULL) {
                pr_err("gs_put_char: NULL port pointer\n");
-               return;
+               return 0;
        }
 
        gs_debug("gs_put_char: (%d,%p) char=0x%x, called from %p\n",
@@ -910,10 +911,11 @@ static void gs_put_char(struct tty_struct *tty, unsigned char ch)
                goto exit;
        }
 
-       gs_buf_put(port->port_write_buf, &ch, 1);
+       ret = gs_buf_put(port->port_write_buf, &ch, 1);
 
 exit:
        spin_unlock_irqrestore(&port->port_lock, flags);
+       return ret;
 }
 
 /*
index 878e428a0ec12b3fd45c9298b40fa058220f5881..4154be375c7a01a48ac3ab26eeeeb78c7c62b1ab 100644 (file)
@@ -74,7 +74,7 @@ static int utf8_to_utf16le(const char *s, __le16 *cp, unsigned len)
                                goto fail;
                } else
                        uchar = c;
-               put_unaligned (cpu_to_le16 (uchar), cp++);
+               put_unaligned_le16(uchar, cp++);
                count++;
                len--;
        }
index f13d1029aeb2000fc814b4bc3e3c1db49ee9259f..382587c4457ccae83396be87280da2bf0da190ad 100644 (file)
@@ -770,7 +770,7 @@ static int ehci_hub_control (
        if (status & ~0xffff)   /* only if wPortChange is interesting */
 #endif
                dbg_port (ehci, "GetStatus", wIndex + 1, temp);
-               put_unaligned(cpu_to_le32 (status), (__le32 *) buf);
+               put_unaligned_le32(status, buf);
                break;
        case SetHubFeature:
                switch (wValue) {
index 5be3bb3e6a9d791aa6262af9e429f724f20066f3..17dc2eccda83e7d6dca6bfd725fbd87fdce8b649 100644 (file)
@@ -736,14 +736,14 @@ static int ohci_hub_control (
                break;
        case GetHubStatus:
                temp = roothub_status (ohci) & ~(RH_HS_CRWE | RH_HS_DRWE);
-               put_unaligned(cpu_to_le32 (temp), (__le32 *) buf);
+               put_unaligned_le32(temp, buf);
                break;
        case GetPortStatus:
                if (!wIndex || wIndex > ports)
                        goto error;
                wIndex--;
                temp = roothub_portstatus (ohci, wIndex);
-               put_unaligned(cpu_to_le32 (temp), (__le32 *) buf);
+               put_unaligned_le32(temp, buf);
 
 #ifndef        OHCI_VERBOSE_DEBUG
        if (*(u16*)(buf+2))     /* only if wPortChange is interesting */
index 3fd7a0c120787789dd385b10a9db004c08af2ab6..426575247b23697265487a995e2551371f88361b 100644 (file)
@@ -1506,15 +1506,7 @@ static const char proc_filename[] = "driver/sl811h";
 
 static void create_debug_file(struct sl811 *sl811)
 {
-       struct proc_dir_entry *pde;
-
-       pde = create_proc_entry(proc_filename, 0, NULL);
-       if (pde == NULL)
-               return;
-
-       pde->proc_fops = &proc_ops;
-       pde->data = sl811;
-       sl811->pde = pde;
+       sl811->pde = proc_create_data(proc_filename, 0, NULL, &proc_ops, sl811);
 }
 
 static void remove_debug_file(struct sl811 *sl811)
index d17d1645714fbb2ab9ee7cf391181b62e869275a..04a56f300ea68059ce54d7f803408737562855ab 100644 (file)
@@ -1421,8 +1421,7 @@ static void digi_close(struct usb_serial_port *port, struct file *filp)
                tty_wait_until_sent(tty, DIGI_CLOSE_TIMEOUT);
 
        /* flush driver and line discipline buffers */
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       tty_driver_flush_buffer(tty);
        tty_ldisc_flush(tty);
 
        if (port->serial->dev) {
index a9934a3f984591700cfa64e8dce7d31900035c64..0cb0d77dc429b2b5d0f0dbd916feac063db7a4f6 100644 (file)
@@ -296,16 +296,14 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int
        struct usb_serial_port *port = tty->driver_data;
        int retval = -ENODEV;
 
-       if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED)
+       if (port->serial->dev->state == USB_STATE_NOTATTACHED)
                goto exit;
 
        dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
 
-       if (!port->open_count) {
-               retval = -EINVAL;
-               dbg("%s - port not opened", __func__);
-               goto exit;
-       }
+       /* open_count is managed under the mutex lock for the tty so cannot
+           drop to zero until after the last close completes */
+       WARN_ON(!port->open_count);
 
        /* pass on to the driver specific version of this function */
        retval = port->serial->type->write(port, buf, count);
@@ -317,61 +315,28 @@ exit:
 static int serial_write_room (struct tty_struct *tty) 
 {
        struct usb_serial_port *port = tty->driver_data;
-       int retval = -ENODEV;
-
-       if (!port)
-               goto exit;
-
        dbg("%s - port %d", __func__, port->number);
-
-       if (!port->open_count) {
-               dbg("%s - port not open", __func__);
-               goto exit;
-       }
-
+       WARN_ON(!port->open_count);
        /* pass on to the driver specific version of this function */
-       retval = port->serial->type->write_room(port);
-
-exit:
-       return retval;
+       return port->serial->type->write_room(port);
 }
 
 static int serial_chars_in_buffer (struct tty_struct *tty) 
 {
        struct usb_serial_port *port = tty->driver_data;
-       int retval = -ENODEV;
-
-       if (!port)
-               goto exit;
-
        dbg("%s = port %d", __func__, port->number);
 
-       if (!port->open_count) {
-               dbg("%s - port not open", __func__);
-               goto exit;
-       }
-
+       WARN_ON(!port->open_count);
        /* pass on to the driver specific version of this function */
-       retval = port->serial->type->chars_in_buffer(port);
-
-exit:
-       return retval;
+       return port->serial->type->chars_in_buffer(port);
 }
 
 static void serial_throttle (struct tty_struct * tty)
 {
        struct usb_serial_port *port = tty->driver_data;
-
-       if (!port)
-               return;
-
        dbg("%s - port %d", __func__, port->number);
 
-       if (!port->open_count) {
-               dbg ("%s - port not open", __func__);
-               return;
-       }
-
+       WARN_ON(!port->open_count);
        /* pass on to the driver specific version of this function */
        if (port->serial->type->throttle)
                port->serial->type->throttle(port);
@@ -380,17 +345,9 @@ static void serial_throttle (struct tty_struct * tty)
 static void serial_unthrottle (struct tty_struct * tty)
 {
        struct usb_serial_port *port = tty->driver_data;
-
-       if (!port)
-               return;
-
        dbg("%s - port %d", __func__, port->number);
 
-       if (!port->open_count) {
-               dbg("%s - port not open", __func__);
-               return;
-       }
-
+       WARN_ON(!port->open_count);
        /* pass on to the driver specific version of this function */
        if (port->serial->type->unthrottle)
                port->serial->type->unthrottle(port);
@@ -401,42 +358,27 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned in
        struct usb_serial_port *port = tty->driver_data;
        int retval = -ENODEV;
 
-       lock_kernel();
-       if (!port)
-               goto exit;
-
        dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
 
-       /* Caution - port->open_count is BKL protected */
-       if (!port->open_count) {
-               dbg ("%s - port not open", __func__);
-               goto exit;
-       }
+       WARN_ON(!port->open_count);
 
        /* pass on to the driver specific version of this function if it is available */
-       if (port->serial->type->ioctl)
+       if (port->serial->type->ioctl) {
+               lock_kernel();
                retval = port->serial->type->ioctl(port, file, cmd, arg);
+               unlock_kernel();
+       }
        else
                retval = -ENOIOCTLCMD;
-exit:
-       unlock_kernel();
        return retval;
 }
 
 static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
 {
        struct usb_serial_port *port = tty->driver_data;
-
-       if (!port)
-               return;
-
        dbg("%s - port %d", __func__, port->number);
 
-       if (!port->open_count) {
-               dbg("%s - port not open", __func__);
-               return;
-       }
-
+       WARN_ON(!port->open_count);
        /* pass on to the driver specific version of this function if it is available */
        if (port->serial->type->set_termios)
                port->serial->type->set_termios(port, old);
@@ -448,24 +390,15 @@ static void serial_break (struct tty_struct *tty, int break_state)
 {
        struct usb_serial_port *port = tty->driver_data;
 
-       lock_kernel();
-       if (!port) {
-               unlock_kernel();
-               return;
-       }
-
        dbg("%s - port %d", __func__, port->number);
 
-       if (!port->open_count) {
-               dbg("%s - port not open", __func__);
-               unlock_kernel();
-               return;
-       }
-
+       WARN_ON(!port->open_count);
        /* pass on to the driver specific version of this function if it is available */
-       if (port->serial->type->break_ctl)
+       if (port->serial->type->break_ctl) {
+               lock_kernel();
                port->serial->type->break_ctl(port, break_state);
-       unlock_kernel();
+               unlock_kernel();
+       }
 }
 
 static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
@@ -519,19 +452,11 @@ static int serial_tiocmget (struct tty_struct *tty, struct file *file)
 {
        struct usb_serial_port *port = tty->driver_data;
 
-       if (!port)
-               return -ENODEV;
-
        dbg("%s - port %d", __func__, port->number);
 
-       if (!port->open_count) {
-               dbg("%s - port not open", __func__);
-               return -ENODEV;
-       }
-
+       WARN_ON(!port->open_count);
        if (port->serial->type->tiocmget)
                return port->serial->type->tiocmget(port, file);
-
        return -EINVAL;
 }
 
@@ -540,19 +465,11 @@ static int serial_tiocmset (struct tty_struct *tty, struct file *file,
 {
        struct usb_serial_port *port = tty->driver_data;
 
-       if (!port)
-               return -ENODEV;
-
        dbg("%s - port %d", __func__, port->number);
 
-       if (!port->open_count) {
-               dbg("%s - port not open", __func__);
-               return -ENODEV;
-       }
-
+       WARN_ON(!port->open_count);
        if (port->serial->type->tiocmset)
                return port->serial->type->tiocmset(port, file, set, clear);
-
        return -EINVAL;
 }
 
index e96bf8663ffcd0eef052e334a0ecca8b430f628a..f07e8a4c1f3ddb3b3cfe12f4a3b22bef7e7c11a9 100644 (file)
@@ -673,15 +673,13 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
        }
 */
 
-       if (port->tty->driver->flush_buffer)
-               port->tty->driver->flush_buffer(port->tty);
+       tty_driver_flush_buffer(port->tty);
        tty_ldisc_flush(port->tty);
 
        firm_report_tx_done(port);
 
        firm_close(port);
 
-printk(KERN_ERR"Before processing rx_urbs_submitted.\n");
        /* shutdown our bulk reads and writes */
        mutex_lock(&info->deathwarrant);
        spin_lock_irq(&info->lock);
index a576dc2617320956f99184091fb0a17fe9c83fc4..bb1dadaa4a23a1054cca3fbd56791d3cf50fcb1d 100644 (file)
@@ -1774,6 +1774,11 @@ config FB_PXA
 
          If unsure, say N.
 
+config FB_PXA_SMARTPANEL
+       bool "PXA Smartpanel LCD support"
+       default n
+       depends on FB_PXA
+
 config FB_PXA_PARAMETERS
        bool "PXA LCD command line parameters"
        default n
index 17b5267f44d7a2842fffe08e08708fa2e63f441e..9f8a389dc7aedaae23368286f60ce3c973ae5bc9 100644 (file)
@@ -381,7 +381,7 @@ int __init clps711xfb_init(void)
 
        /* Register the /proc entries. */
        clps7111fb_backlight_proc_entry = create_proc_entry("backlight", 0444,
-               &proc_root);
+               NULL);
        if (clps7111fb_backlight_proc_entry == NULL) {
                printk("Couldn't create the /proc entry for the backlight.\n");
                return -EINVAL;
index 8eda7b60df8f76bfdf4d7b8050ba50df4e43c214..ad31983b43eb6a169a100b2846e96f1554e32b1b 100644 (file)
@@ -1881,7 +1881,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
                        scr_memsetw((unsigned short *) (vc->vc_origin +
                                                        vc->vc_size_row *
                                                        (b - count)),
-                                   vc->vc_video_erase_char,
+                                   vc->vc_scrl_erase_char,
                                    vc->vc_size_row * count);
                        return 1;
                        break;
@@ -1953,7 +1953,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
                        scr_memsetw((unsigned short *) (vc->vc_origin +
                                                        vc->vc_size_row *
                                                        (b - count)),
-                                   vc->vc_video_erase_char,
+                                   vc->vc_scrl_erase_char,
                                    vc->vc_size_row * count);
                        return 1;
                }
@@ -1972,7 +1972,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
                        scr_memsetw((unsigned short *) (vc->vc_origin +
                                                        vc->vc_size_row *
                                                        t),
-                                   vc->vc_video_erase_char,
+                                   vc->vc_scrl_erase_char,
                                    vc->vc_size_row * count);
                        return 1;
                        break;
@@ -2042,7 +2042,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
                        scr_memsetw((unsigned short *) (vc->vc_origin +
                                                        vc->vc_size_row *
                                                        t),
-                                   vc->vc_video_erase_char,
+                                   vc->vc_scrl_erase_char,
                                    vc->vc_size_row * count);
                        return 1;
                }
index bd8d995fe25de13a1a0fa7444ba35eef58ded727..38a296bbdfc97a9a67ba1c0d74d2a81357698989 100644 (file)
@@ -531,7 +531,7 @@ static void mdacon_cursor(struct vc_data *c, int mode)
 
 static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
 {
-       u16 eattr = mda_convert_attr(c->vc_video_erase_char);
+       u16 eattr = mda_convert_attr(c->vc_scrl_erase_char);
 
        if (!lines)
                return 0;
index 67a682d6cc7bb03ba043753d4585928b248f1b6f..a11cc2fdd4cd5eb59eb714652b108c3f825b507c 100644 (file)
@@ -170,12 +170,12 @@ static int sticon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
     switch (dir) {
     case SM_UP:
        sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols);
-       sti_clear(sti, b - count, 0, count, conp->vc_cols, conp->vc_video_erase_char);
+       sti_clear(sti, b - count, 0, count, conp->vc_cols, conp->vc_scrl_erase_char);
        break;
 
     case SM_DOWN:
        sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols);
-       sti_clear(sti, t, 0, count, conp->vc_cols, conp->vc_video_erase_char);
+       sti_clear(sti, t, 0, count, conp->vc_cols, conp->vc_scrl_erase_char);
        break;
     }
 
index 6df29a62d7202552d63ced7bfc588ef8854d6c49..bd1f57b259d9ce50d470b192e021ad95461b8e72 100644 (file)
@@ -1350,7 +1350,7 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
                } else
                        c->vc_origin += delta;
                scr_memsetw((u16 *) (c->vc_origin + c->vc_screenbuf_size -
-                                    delta), c->vc_video_erase_char,
+                                    delta), c->vc_scrl_erase_char,
                            delta);
        } else {
                if (oldo - delta < vga_vram_base) {
@@ -1363,7 +1363,7 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
                } else
                        c->vc_origin -= delta;
                c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
-               scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char,
+               scr_memsetw((u16 *) (c->vc_origin), c->vc_scrl_erase_char,
                            delta);
        }
        c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
index aaa3e538e5da52c04043cc4ec781e89784ecd1a5..5b5f072fc1a818f57ec989daaac4c0afef79ddb4 100644 (file)
@@ -522,8 +522,6 @@ static void parse_bios(unsigned char __iomem* vbios, struct matrox_bios* bd) {
 #endif
 }
 
-#define get_u16(x) (le16_to_cpu(get_unaligned((__u16*)(x))))
-#define get_u32(x) (le32_to_cpu(get_unaligned((__u32*)(x))))
 static int parse_pins1(WPMINFO const struct matrox_bios* bd) {
        unsigned int maxdac;
 
@@ -532,11 +530,12 @@ static int parse_pins1(WPMINFO const struct matrox_bios* bd) {
                case 1:         maxdac = 220000; break;
                default:        maxdac = 240000; break;
        }
-       if (get_u16(bd->pins + 24)) {
-               maxdac = get_u16(bd->pins + 24) * 10;
+       if (get_unaligned_le16(bd->pins + 24)) {
+               maxdac = get_unaligned_le16(bd->pins + 24) * 10;
        }
        MINFO->limits.pixel.vcomax = maxdac;
-       MINFO->values.pll.system = get_u16(bd->pins + 28) ? get_u16(bd->pins + 28) * 10 : 50000;
+       MINFO->values.pll.system = get_unaligned_le16(bd->pins + 28) ?
+               get_unaligned_le16(bd->pins + 28) * 10 : 50000;
        /* ignore 4MB, 8MB, module clocks */
        MINFO->features.pll.ref_freq = 14318;
        MINFO->values.reg.mctlwtst      = 0x00030101;
@@ -575,7 +574,8 @@ static void default_pins2(WPMINFO2) {
 static int parse_pins3(WPMINFO const struct matrox_bios* bd) {
        MINFO->limits.pixel.vcomax      =
        MINFO->limits.system.vcomax     = (bd->pins[36] == 0xFF) ? 230000                       : ((bd->pins[36] + 100) * 1000);
-       MINFO->values.reg.mctlwtst      = get_u32(bd->pins + 48) == 0xFFFFFFFF ? 0x01250A21     : get_u32(bd->pins + 48);
+       MINFO->values.reg.mctlwtst      = get_unaligned_le32(bd->pins + 48) == 0xFFFFFFFF ?
+               0x01250A21 : get_unaligned_le32(bd->pins + 48);
        /* memory config */
        MINFO->values.reg.memrdbk       = ((bd->pins[57] << 21) & 0x1E000000) |
                                          ((bd->pins[57] << 22) & 0x00C00000) |
@@ -601,7 +601,7 @@ static void default_pins3(WPMINFO2) {
 static int parse_pins4(WPMINFO const struct matrox_bios* bd) {
        MINFO->limits.pixel.vcomax      = (bd->pins[ 39] == 0xFF) ? 230000                      : bd->pins[ 39] * 4000;
        MINFO->limits.system.vcomax     = (bd->pins[ 38] == 0xFF) ? MINFO->limits.pixel.vcomax  : bd->pins[ 38] * 4000;
-       MINFO->values.reg.mctlwtst      = get_u32(bd->pins + 71);
+       MINFO->values.reg.mctlwtst      = get_unaligned_le32(bd->pins + 71);
        MINFO->values.reg.memrdbk       = ((bd->pins[87] << 21) & 0x1E000000) |
                                          ((bd->pins[87] << 22) & 0x00C00000) |
                                          ((bd->pins[86] <<  1) & 0x000001E0) |
@@ -609,7 +609,7 @@ static int parse_pins4(WPMINFO const struct matrox_bios* bd) {
        MINFO->values.reg.opt           = ((bd->pins[53] << 15) & 0x00400000) |
                                          ((bd->pins[53] << 22) & 0x10000000) |
                                          ((bd->pins[53] <<  7) & 0x00001C00);
-       MINFO->values.reg.opt3          = get_u32(bd->pins + 67);
+       MINFO->values.reg.opt3          = get_unaligned_le32(bd->pins + 67);
        MINFO->values.pll.system        = (bd->pins[ 65] == 0xFF) ? 200000                      : bd->pins[ 65] * 4000;
        MINFO->features.pll.ref_freq    = (bd->pins[ 92] & 0x01) ? 14318 : 27000;
        return 0;
@@ -640,12 +640,12 @@ static int parse_pins5(WPMINFO const struct matrox_bios* bd) {
        MINFO->limits.video.vcomin      = (bd->pins[122] == 0xFF) ? MINFO->limits.system.vcomin : bd->pins[122] * mult;
        MINFO->values.pll.system        =
        MINFO->values.pll.video         = (bd->pins[ 92] == 0xFF) ? 284000                      : bd->pins[ 92] * 4000;
-       MINFO->values.reg.opt           = get_u32(bd->pins+ 48);
-       MINFO->values.reg.opt2          = get_u32(bd->pins+ 52);
-       MINFO->values.reg.opt3          = get_u32(bd->pins+ 94);
-       MINFO->values.reg.mctlwtst      = get_u32(bd->pins+ 98);
-       MINFO->values.reg.memmisc       = get_u32(bd->pins+102);
-       MINFO->values.reg.memrdbk       = get_u32(bd->pins+106);
+       MINFO->values.reg.opt           = get_unaligned_le32(bd->pins + 48);
+       MINFO->values.reg.opt2          = get_unaligned_le32(bd->pins + 52);
+       MINFO->values.reg.opt3          = get_unaligned_le32(bd->pins + 94);
+       MINFO->values.reg.mctlwtst      = get_unaligned_le32(bd->pins + 98);
+       MINFO->values.reg.memmisc       = get_unaligned_le32(bd->pins + 102);
+       MINFO->values.reg.memrdbk       = get_unaligned_le32(bd->pins + 106);
        MINFO->features.pll.ref_freq    = (bd->pins[110] & 0x01) ? 14318 : 27000;
        MINFO->values.memory.ddr        = (bd->pins[114] & 0x60) == 0x20;
        MINFO->values.memory.dll        = (bd->pins[115] & 0x02) != 0;
index 249791286367ea934b6d149799d1571b0b6e13c7..cc4c038a1b3f3c8c22821aab37a54f564ba41d8b 100644 (file)
@@ -206,8 +206,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
        }
 
        /* check waveform mode table address checksum */
-       wmta = le32_to_cpu(get_unaligned((__le32 *) wfm_hdr->wmta));
-       wmta &= 0x00FFFFFF;
+       wmta = get_unaligned_le32(wfm_hdr->wmta) & 0x00FFFFFF;
        cksum_idx = wmta + m*4 + 3;
        if (cksum_idx > size)
                return -EINVAL;
@@ -219,8 +218,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
        }
 
        /* check waveform temperature table address checksum */
-       tta = le32_to_cpu(get_unaligned((int *) (mem + wmta + m*4)));
-       tta &= 0x00FFFFFF;
+       tta = get_unaligned_le32(mem + wmta + m * 4) & 0x00FFFFFF;
        cksum_idx = tta + trn*4 + 3;
        if (cksum_idx > size)
                return -EINVAL;
@@ -233,8 +231,7 @@ static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
 
        /* here we do the real work of putting the waveform into the
        metromem buffer. this does runlength decoding of the waveform */
-       wfm_idx = le32_to_cpu(get_unaligned((__le32 *) (mem + tta + trn*4)));
-       wfm_idx &= 0x00FFFFFF;
+       wfm_idx = get_unaligned_le32(mem + tta + trn * 4) & 0x00FFFFFF;
        owfm_idx = wfm_idx;
        if (wfm_idx > size)
                return -EINVAL;
index 757651954e6cf81bebba98cda2bf36ce910f824d..3ab6e3d973a1670bef82cc28fa89cf1ba8e46d8f 100644 (file)
@@ -39,6 +39,9 @@
 #include <linux/dma-mapping.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/completion.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include "pxafb.h"
 
 /* Bits which should not be set in machine configuration structures */
-#define LCCR0_INVALID_CONFIG_MASK (LCCR0_OUM|LCCR0_BM|LCCR0_QDM|LCCR0_DIS|LCCR0_EFM|LCCR0_IUM|LCCR0_SFM|LCCR0_LDM|LCCR0_ENB)
-#define LCCR3_INVALID_CONFIG_MASK (LCCR3_HSP|LCCR3_VSP|LCCR3_PCD|LCCR3_BPP)
+#define LCCR0_INVALID_CONFIG_MASK      (LCCR0_OUM | LCCR0_BM | LCCR0_QDM |\
+                                        LCCR0_DIS | LCCR0_EFM | LCCR0_IUM |\
+                                        LCCR0_SFM | LCCR0_LDM | LCCR0_ENB)
+
+#define LCCR3_INVALID_CONFIG_MASK      (LCCR3_HSP | LCCR3_VSP |\
+                                        LCCR3_PCD | LCCR3_BPP)
 
 static void (*pxafb_backlight_power)(int);
 static void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
 
-static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *);
+static int pxafb_activate_var(struct fb_var_screeninfo *var,
+                               struct pxafb_info *);
 static void set_ctrlr_state(struct pxafb_info *fbi, u_int state);
 
-#ifdef CONFIG_FB_PXA_PARAMETERS
-#define PXAFB_OPTIONS_SIZE 256
-static char g_options[PXAFB_OPTIONS_SIZE] __devinitdata = "";
-#endif
+static inline unsigned long
+lcd_readl(struct pxafb_info *fbi, unsigned int off)
+{
+       return __raw_readl(fbi->mmio_base + off);
+}
+
+static inline void
+lcd_writel(struct pxafb_info *fbi, unsigned int off, unsigned long val)
+{
+       __raw_writel(val, fbi->mmio_base + off);
+}
 
 static inline void pxafb_schedule_work(struct pxafb_info *fbi, u_int state)
 {
@@ -79,10 +94,12 @@ static inline void pxafb_schedule_work(struct pxafb_info *fbi, u_int state)
        /*
         * We need to handle two requests being made at the same time.
         * There are two important cases:
-        *  1. When we are changing VT (C_REENABLE) while unblanking (C_ENABLE)
-        *     We must perform the unblanking, which will do our REENABLE for us.
-        *  2. When we are blanking, but immediately unblank before we have
-        *     blanked.  We do the "REENABLE" thing here as well, just to be sure.
+        *  1. When we are changing VT (C_REENABLE) while unblanking
+        *     (C_ENABLE) We must perform the unblanking, which will
+        *     do our REENABLE for us.
+        *  2. When we are blanking, but immediately unblank before
+        *     we have blanked.  We do the "REENABLE" thing here as
+        *     well, just to be sure.
         */
        if (fbi->task_state == C_ENABLE && state == C_REENABLE)
                state = (u_int) -1;
@@ -129,13 +146,13 @@ pxafb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,
                val  = ((red   << 8) & 0x00f80000);
                val |= ((green >> 0) & 0x0000fc00);
                val |= ((blue  >> 8) & 0x000000f8);
-               ((u32*)(fbi->palette_cpu))[regno] = val;
+               ((u32 *)(fbi->palette_cpu))[regno] = val;
                break;
        case LCCR4_PAL_FOR_2:
                val  = ((red   << 8) & 0x00fc0000);
                val |= ((green >> 0) & 0x0000fc00);
                val |= ((blue  >> 8) & 0x000000fc);
-               ((u32*)(fbi->palette_cpu))[regno] = val;
+               ((u32 *)(fbi->palette_cpu))[regno] = val;
                break;
        }
 
@@ -203,15 +220,15 @@ pxafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  */
 static int pxafb_bpp_to_lccr3(struct fb_var_screeninfo *var)
 {
-        int ret = 0;
-        switch (var->bits_per_pixel) {
-        case 1:  ret = LCCR3_1BPP; break;
-        case 2:  ret = LCCR3_2BPP; break;
-        case 4:  ret = LCCR3_4BPP; break;
-        case 8:  ret = LCCR3_8BPP; break;
-        case 16: ret = LCCR3_16BPP; break;
-        }
-        return ret;
+       int ret = 0;
+       switch (var->bits_per_pixel) {
+       case 1:  ret = LCCR3_1BPP; break;
+       case 2:  ret = LCCR3_2BPP; break;
+       case 4:  ret = LCCR3_4BPP; break;
+       case 8:  ret = LCCR3_8BPP; break;
+       case 16: ret = LCCR3_16BPP; break;
+       }
+       return ret;
 }
 
 #ifdef CONFIG_CPU_FREQ
@@ -223,31 +240,32 @@ static int pxafb_bpp_to_lccr3(struct fb_var_screeninfo *var)
  */
 static unsigned int pxafb_display_dma_period(struct fb_var_screeninfo *var)
 {
-       /*
-        * Period = pixclock * bits_per_byte * bytes_per_transfer
-        *              / memory_bits_per_pixel;
-        */
-       return var->pixclock * 8 * 16 / var->bits_per_pixel;
+       /*
+        * Period = pixclock * bits_per_byte * bytes_per_transfer
+        *              / memory_bits_per_pixel;
+        */
+       return var->pixclock * 8 * 16 / var->bits_per_pixel;
 }
-
-extern unsigned int get_clk_frequency_khz(int info);
 #endif
 
 /*
  * Select the smallest mode that allows the desired resolution to be
  * displayed. If desired parameters can be rounded up.
  */
-static struct pxafb_mode_info *pxafb_getmode(struct pxafb_mach_info *mach, struct fb_var_screeninfo *var)
+static struct pxafb_mode_info *pxafb_getmode(struct pxafb_mach_info *mach,
+                                            struct fb_var_screeninfo *var)
 {
        struct pxafb_mode_info *mode = NULL;
        struct pxafb_mode_info *modelist = mach->modes;
        unsigned int best_x = 0xffffffff, best_y = 0xffffffff;
        unsigned int i;
 
-       for (i = 0 ; i < mach->num_modes ; i++) {
-               if (modelist[i].xres >= var->xres && modelist[i].yres >= var->yres &&
-                               modelist[i].xres < best_x && modelist[i].yres < best_y &&
-                               modelist[i].bpp >= var->bits_per_pixel ) {
+       for (i = 0; i < mach->num_modes; i++) {
+               if (modelist[i].xres >= var->xres &&
+                   modelist[i].yres >= var->yres &&
+                   modelist[i].xres < best_x &&
+                   modelist[i].yres < best_y &&
+                   modelist[i].bpp >= var->bits_per_pixel) {
                        best_x = modelist[i].xres;
                        best_y = modelist[i].yres;
                        mode = &modelist[i];
@@ -257,7 +275,8 @@ static struct pxafb_mode_info *pxafb_getmode(struct pxafb_mach_info *mach, struc
        return mode;
 }
 
-static void pxafb_setmode(struct fb_var_screeninfo *var, struct pxafb_mode_info *mode)
+static void pxafb_setmode(struct fb_var_screeninfo *var,
+                         struct pxafb_mode_info *mode)
 {
        var->xres               = mode->xres;
        var->yres               = mode->yres;
@@ -315,19 +334,20 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
        var->yres_virtual =
                max(var->yres_virtual, var->yres);
 
-        /*
+       /*
         * Setup the RGB parameters for this display.
         *
         * The pixel packing format is described on page 7-11 of the
         * PXA2XX Developer's Manual.
-         */
+        */
        if (var->bits_per_pixel == 16) {
                var->red.offset   = 11; var->red.length   = 5;
                var->green.offset = 5;  var->green.length = 6;
                var->blue.offset  = 0;  var->blue.length  = 5;
                var->transp.offset = var->transp.length = 0;
        } else {
-               var->red.offset = var->green.offset = var->blue.offset = var->transp.offset = 0;
+               var->red.offset = var->green.offset = 0;
+               var->blue.offset = var->transp.offset = 0;
                var->red.length   = 8;
                var->green.length = 8;
                var->blue.length  = 8;
@@ -345,8 +365,7 @@ static int pxafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 
 static inline void pxafb_set_truecolor(u_int is_true_color)
 {
-       pr_debug("pxafb: true_color = %d\n", is_true_color);
-       // do your machine-specific setup if needed
+       /* do your machine-specific setup if needed */
 }
 
 /*
@@ -357,9 +376,6 @@ static int pxafb_set_par(struct fb_info *info)
 {
        struct pxafb_info *fbi = (struct pxafb_info *)info;
        struct fb_var_screeninfo *var = &info->var;
-       unsigned long palette_mem_size;
-
-       pr_debug("pxafb: set_par\n");
 
        if (var->bits_per_pixel == 16)
                fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
@@ -379,17 +395,10 @@ static int pxafb_set_par(struct fb_info *info)
        if (var->bits_per_pixel == 16)
                fbi->palette_size = 0;
        else
-               fbi->palette_size = var->bits_per_pixel == 1 ? 4 : 1 << var->bits_per_pixel;
-
-       if ((fbi->lccr4 & LCCR4_PAL_FOR_MASK) == LCCR4_PAL_FOR_0)
-               palette_mem_size = fbi->palette_size * sizeof(u16);
-       else
-               palette_mem_size = fbi->palette_size * sizeof(u32);
-
-       pr_debug("pxafb: palette_mem_size = 0x%08lx\n", palette_mem_size);
+               fbi->palette_size = var->bits_per_pixel == 1 ?
+                                       4 : 1 << var->bits_per_pixel;
 
-       fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
-       fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
+       fbi->palette_cpu = (u16 *)&fbi->dma_buff->palette[0];
 
        /*
         * Set (any) board control register to handle new color depth
@@ -406,36 +415,6 @@ static int pxafb_set_par(struct fb_info *info)
        return 0;
 }
 
-/*
- * Formal definition of the VESA spec:
- *  On
- *     This refers to the state of the display when it is in full operation
- *  Stand-By
- *     This defines an optional operating state of minimal power reduction with
- *     the shortest recovery time
- *  Suspend
- *     This refers to a level of power management in which substantial power
- *     reduction is achieved by the display.  The display can have a longer
- *     recovery time from this state than from the Stand-by state
- *  Off
- *     This indicates that the display is consuming the lowest level of power
- *     and is non-operational. Recovery from this state may optionally require
- *     the user to manually power on the monitor
- *
- *  Now, the fbdev driver adds an additional state, (blank), where they
- *  turn off the video (maybe by colormap tricks), but don't mess with the
- *  video itself: think of it semantically between on and Stand-By.
- *
- *  So here's what we should do in our fbdev blank routine:
- *
- *     VESA_NO_BLANKING (mode 0)       Video on,  front/back light on
- *     VESA_VSYNC_SUSPEND (mode 1)     Video on,  front/back light off
- *     VESA_HSYNC_SUSPEND (mode 2)     Video on,  front/back light off
- *     VESA_POWERDOWN (mode 3)         Video off, front/back light off
- *
- *  This will match the matrox implementation.
- */
-
 /*
  * pxafb_blank():
  *     Blank the display by setting all palette values to zero.  Note, the
@@ -447,8 +426,6 @@ static int pxafb_blank(int blank, struct fb_info *info)
        struct pxafb_info *fbi = (struct pxafb_info *)info;
        int i;
 
-       pr_debug("pxafb: blank=%d\n", blank);
-
        switch (blank) {
        case FB_BLANK_POWERDOWN:
        case FB_BLANK_VSYNC_SUSPEND:
@@ -460,11 +437,11 @@ static int pxafb_blank(int blank, struct fb_info *info)
                                pxafb_setpalettereg(i, 0, 0, 0, 0, info);
 
                pxafb_schedule_work(fbi, C_DISABLE);
-               //TODO if (pxafb_blank_helper) pxafb_blank_helper(blank);
+               /* TODO if (pxafb_blank_helper) pxafb_blank_helper(blank); */
                break;
 
        case FB_BLANK_UNBLANK:
-               //TODO if (pxafb_blank_helper) pxafb_blank_helper(blank);
+               /* TODO if (pxafb_blank_helper) pxafb_blank_helper(blank); */
                if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
                    fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
                        fb_set_cmap(&fbi->fb.cmap, info);
@@ -480,7 +457,7 @@ static int pxafb_mmap(struct fb_info *info,
        unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
 
        if (off < info->fix.smem_len) {
-               vma->vm_pgoff += 1;
+               vma->vm_pgoff += fbi->video_offset / PAGE_SIZE;
                return dma_mmap_writecombine(fbi->dev, vma, fbi->map_cpu,
                                             fbi->map_dma, fbi->map_size);
        }
@@ -529,7 +506,8 @@ static struct fb_ops pxafb_ops = {
  *
  * Factoring the 10^4 and 10^-12 out gives 10^-8 == 1 / 100000000 as used below.
  */
-static inline unsigned int get_pcd(struct pxafb_info *fbi, unsigned int pixclock)
+static inline unsigned int get_pcd(struct pxafb_info *fbi,
+                                  unsigned int pixclock)
 {
        unsigned long long pcd;
 
@@ -555,7 +533,7 @@ static inline void set_hsync_time(struct pxafb_info *fbi, unsigned int pcd)
        unsigned long htime;
 
        if ((pcd == 0) || (fbi->fb.var.hsync_len == 0)) {
-               fbi->hsync_time=0;
+               fbi->hsync_time = 0;
                return;
        }
 
@@ -576,71 +554,231 @@ unsigned long pxafb_get_hsync_time(struct device *dev)
 }
 EXPORT_SYMBOL(pxafb_get_hsync_time);
 
-/*
- * pxafb_activate_var():
- *     Configures LCD Controller based on entries in var parameter.  Settings are
- *     only written to the controller if changes were made.
- */
-static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *fbi)
+static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal,
+               unsigned int offset, size_t size)
 {
-       struct pxafb_lcd_reg new_regs;
-       u_long flags;
-       u_int lines_per_panel, pcd = get_pcd(fbi, var->pixclock);
+       struct pxafb_dma_descriptor *dma_desc, *pal_desc;
+       unsigned int dma_desc_off, pal_desc_off;
 
-       pr_debug("pxafb: Configuring PXA LCD\n");
+       if (dma < 0 || dma >= DMA_MAX)
+               return -EINVAL;
 
-       pr_debug("var: xres=%d hslen=%d lm=%d rm=%d\n",
-                var->xres, var->hsync_len,
-                var->left_margin, var->right_margin);
-       pr_debug("var: yres=%d vslen=%d um=%d bm=%d\n",
-                var->yres, var->vsync_len,
-                var->upper_margin, var->lower_margin);
-       pr_debug("var: pixclock=%d pcd=%d\n", var->pixclock, pcd);
+       dma_desc = &fbi->dma_buff->dma_desc[dma];
+       dma_desc_off = offsetof(struct pxafb_dma_buff, dma_desc[dma]);
 
-#if DEBUG_VAR
-       if (var->xres < 16        || var->xres > 1024)
-               printk(KERN_ERR "%s: invalid xres %d\n",
-                       fbi->fb.fix.id, var->xres);
-       switch(var->bits_per_pixel) {
-       case 1:
-       case 2:
-       case 4:
-       case 8:
-       case 16:
-               break;
-       default:
-               printk(KERN_ERR "%s: invalid bit depth %d\n",
-                      fbi->fb.fix.id, var->bits_per_pixel);
-               break;
+       dma_desc->fsadr = fbi->screen_dma + offset;
+       dma_desc->fidr  = 0;
+       dma_desc->ldcmd = size;
+
+       if (pal < 0 || pal >= PAL_MAX) {
+               dma_desc->fdadr = fbi->dma_buff_phys + dma_desc_off;
+               fbi->fdadr[dma] = fbi->dma_buff_phys + dma_desc_off;
+       } else {
+               pal_desc = &fbi->dma_buff->pal_desc[dma];
+               pal_desc_off = offsetof(struct pxafb_dma_buff, dma_desc[pal]);
+
+               pal_desc->fsadr = fbi->dma_buff_phys + pal * PALETTE_SIZE;
+               pal_desc->fidr  = 0;
+
+               if ((fbi->lccr4 & LCCR4_PAL_FOR_MASK) == LCCR4_PAL_FOR_0)
+                       pal_desc->ldcmd = fbi->palette_size * sizeof(u16);
+               else
+                       pal_desc->ldcmd = fbi->palette_size * sizeof(u32);
+
+               pal_desc->ldcmd |= LDCMD_PAL;
+
+               /* flip back and forth between palette and frame buffer */
+               pal_desc->fdadr = fbi->dma_buff_phys + dma_desc_off;
+               dma_desc->fdadr = fbi->dma_buff_phys + pal_desc_off;
+               fbi->fdadr[dma] = fbi->dma_buff_phys + dma_desc_off;
        }
-       if (var->hsync_len < 1    || var->hsync_len > 64)
-               printk(KERN_ERR "%s: invalid hsync_len %d\n",
-                       fbi->fb.fix.id, var->hsync_len);
-       if (var->left_margin < 1  || var->left_margin > 255)
-               printk(KERN_ERR "%s: invalid left_margin %d\n",
-                       fbi->fb.fix.id, var->left_margin);
-       if (var->right_margin < 1 || var->right_margin > 255)
-               printk(KERN_ERR "%s: invalid right_margin %d\n",
-                       fbi->fb.fix.id, var->right_margin);
-       if (var->yres < 1         || var->yres > 1024)
-               printk(KERN_ERR "%s: invalid yres %d\n",
-                       fbi->fb.fix.id, var->yres);
-       if (var->vsync_len < 1    || var->vsync_len > 64)
-               printk(KERN_ERR "%s: invalid vsync_len %d\n",
-                       fbi->fb.fix.id, var->vsync_len);
-       if (var->upper_margin < 0 || var->upper_margin > 255)
-               printk(KERN_ERR "%s: invalid upper_margin %d\n",
-                       fbi->fb.fix.id, var->upper_margin);
-       if (var->lower_margin < 0 || var->lower_margin > 255)
-               printk(KERN_ERR "%s: invalid lower_margin %d\n",
-                       fbi->fb.fix.id, var->lower_margin);
-#endif
 
-       new_regs.lccr0 = fbi->lccr0 |
-               (LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM |
-                 LCCR0_QDM | LCCR0_BM  | LCCR0_OUM);
+       return 0;
+}
+
+#ifdef CONFIG_FB_PXA_SMARTPANEL
+static int setup_smart_dma(struct pxafb_info *fbi)
+{
+       struct pxafb_dma_descriptor *dma_desc;
+       unsigned long dma_desc_off, cmd_buff_off;
+
+       dma_desc = &fbi->dma_buff->dma_desc[DMA_CMD];
+       dma_desc_off = offsetof(struct pxafb_dma_buff, dma_desc[DMA_CMD]);
+       cmd_buff_off = offsetof(struct pxafb_dma_buff, cmd_buff);
+
+       dma_desc->fdadr = fbi->dma_buff_phys + dma_desc_off;
+       dma_desc->fsadr = fbi->dma_buff_phys + cmd_buff_off;
+       dma_desc->fidr  = 0;
+       dma_desc->ldcmd = fbi->n_smart_cmds * sizeof(uint16_t);
+
+       fbi->fdadr[DMA_CMD] = dma_desc->fdadr;
+       return 0;
+}
+
+int pxafb_smart_flush(struct fb_info *info)
+{
+       struct pxafb_info *fbi = container_of(info, struct pxafb_info, fb);
+       uint32_t prsr;
+       int ret = 0;
+
+       /* disable controller until all registers are set up */
+       lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB);
+
+       /* 1. make it an even number of commands to align on 32-bit boundary
+        * 2. add the interrupt command to the end of the chain so we can
+        *    keep track of the end of the transfer
+        */
+
+       while (fbi->n_smart_cmds & 1)
+               fbi->smart_cmds[fbi->n_smart_cmds++] = SMART_CMD_NOOP;
+
+       fbi->smart_cmds[fbi->n_smart_cmds++] = SMART_CMD_INTERRUPT;
+       fbi->smart_cmds[fbi->n_smart_cmds++] = SMART_CMD_WAIT_FOR_VSYNC;
+       setup_smart_dma(fbi);
+
+       /* continue to execute next command */
+       prsr = lcd_readl(fbi, PRSR) | PRSR_ST_OK | PRSR_CON_NT;
+       lcd_writel(fbi, PRSR, prsr);
+
+       /* stop the processor in case it executed "wait for sync" cmd */
+       lcd_writel(fbi, CMDCR, 0x0001);
+
+       /* don't send interrupts for fifo underruns on channel 6 */
+       lcd_writel(fbi, LCCR5, LCCR5_IUM(6));
+
+       lcd_writel(fbi, LCCR1, fbi->reg_lccr1);
+       lcd_writel(fbi, LCCR2, fbi->reg_lccr2);
+       lcd_writel(fbi, LCCR3, fbi->reg_lccr3);
+       lcd_writel(fbi, FDADR0, fbi->fdadr[0]);
+       lcd_writel(fbi, FDADR6, fbi->fdadr[6]);
+
+       /* begin sending */
+       lcd_writel(fbi, LCCR0, fbi->reg_lccr0 | LCCR0_ENB);
+
+       if (wait_for_completion_timeout(&fbi->command_done, HZ/2) == 0) {
+               pr_warning("%s: timeout waiting for command done\n",
+                               __func__);
+               ret = -ETIMEDOUT;
+       }
+
+       /* quick disable */
+       prsr = lcd_readl(fbi, PRSR) & ~(PRSR_ST_OK | PRSR_CON_NT);
+       lcd_writel(fbi, PRSR, prsr);
+       lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB);
+       lcd_writel(fbi, FDADR6, 0);
+       fbi->n_smart_cmds = 0;
+       return ret;
+}
+
+int pxafb_smart_queue(struct fb_info *info, uint16_t *cmds, int n_cmds)
+{
+       int i;
+       struct pxafb_info *fbi = container_of(info, struct pxafb_info, fb);
+
+       /* leave 2 commands for INTERRUPT and WAIT_FOR_SYNC */
+       for (i = 0; i < n_cmds; i++) {
+               if (fbi->n_smart_cmds == CMD_BUFF_SIZE - 8)
+                       pxafb_smart_flush(info);
+
+               fbi->smart_cmds[fbi->n_smart_cmds++] = *cmds++;
+       }
+
+       return 0;
+}
+
+static unsigned int __smart_timing(unsigned time_ns, unsigned long lcd_clk)
+{
+       unsigned int t = (time_ns * (lcd_clk / 1000000) / 1000);
+       return (t == 0) ? 1 : t;
+}
+
+static void setup_smart_timing(struct pxafb_info *fbi,
+                               struct fb_var_screeninfo *var)
+{
+       struct pxafb_mach_info *inf = fbi->dev->platform_data;
+       struct pxafb_mode_info *mode = &inf->modes[0];
+       unsigned long lclk = clk_get_rate(fbi->clk);
+       unsigned t1, t2, t3, t4;
+
+       t1 = max(mode->a0csrd_set_hld, mode->a0cswr_set_hld);
+       t2 = max(mode->rd_pulse_width, mode->wr_pulse_width);
+       t3 = mode->op_hold_time;
+       t4 = mode->cmd_inh_time;
+
+       fbi->reg_lccr1 =
+               LCCR1_DisWdth(var->xres) |
+               LCCR1_BegLnDel(__smart_timing(t1, lclk)) |
+               LCCR1_EndLnDel(__smart_timing(t2, lclk)) |
+               LCCR1_HorSnchWdth(__smart_timing(t3, lclk));
+
+       fbi->reg_lccr2 = LCCR2_DisHght(var->yres);
+       fbi->reg_lccr3 = LCCR3_PixClkDiv(__smart_timing(t4, lclk));
+
+       /* FIXME: make this configurable */
+       fbi->reg_cmdcr = 1;
+}
+
+static int pxafb_smart_thread(void *arg)
+{
+       struct pxafb_info *fbi = arg;
+       struct pxafb_mach_info *inf = fbi->dev->platform_data;
+
+       if (!fbi || !inf->smart_update) {
+               pr_err("%s: not properly initialized, thread terminated\n",
+                               __func__);
+               return -EINVAL;
+       }
 
-       new_regs.lccr1 =
+       pr_debug("%s(): task starting\n", __func__);
+
+       set_freezable();
+       while (!kthread_should_stop()) {
+
+               if (try_to_freeze())
+                       continue;
+
+               if (fbi->state == C_ENABLE) {
+                       inf->smart_update(&fbi->fb);
+                       complete(&fbi->refresh_done);
+               }
+
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule_timeout(30 * HZ / 1000);
+       }
+
+       pr_debug("%s(): task ending\n", __func__);
+       return 0;
+}
+
+static int pxafb_smart_init(struct pxafb_info *fbi)
+{
+       fbi->smart_thread = kthread_run(pxafb_smart_thread, fbi,
+                                       "lcd_refresh");
+       if (IS_ERR(fbi->smart_thread)) {
+               printk(KERN_ERR "%s: unable to create kernel thread\n",
+                               __func__);
+               return PTR_ERR(fbi->smart_thread);
+       }
+       return 0;
+}
+#else
+int pxafb_smart_queue(struct fb_info *info, uint16_t *cmds, int n_cmds)
+{
+       return 0;
+}
+
+int pxafb_smart_flush(struct fb_info *info)
+{
+       return 0;
+}
+#endif /* CONFIG_FB_SMART_PANEL */
+
+static void setup_parallel_timing(struct pxafb_info *fbi,
+                                 struct fb_var_screeninfo *var)
+{
+       unsigned int lines_per_panel, pcd = get_pcd(fbi, var->pixclock);
+
+       fbi->reg_lccr1 =
                LCCR1_DisWdth(var->xres) +
                LCCR1_HorSnchWdth(var->hsync_len) +
                LCCR1_BegLnDel(var->left_margin) +
@@ -654,110 +792,118 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *
        if ((fbi->lccr0 & LCCR0_SDS) == LCCR0_Dual)
                lines_per_panel /= 2;
 
-       new_regs.lccr2 =
+       fbi->reg_lccr2 =
                LCCR2_DisHght(lines_per_panel) +
                LCCR2_VrtSnchWdth(var->vsync_len) +
                LCCR2_BegFrmDel(var->upper_margin) +
                LCCR2_EndFrmDel(var->lower_margin);
 
-       new_regs.lccr3 = fbi->lccr3 |
-               pxafb_bpp_to_lccr3(var) |
-               (var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
-               (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL);
+       fbi->reg_lccr3 = fbi->lccr3 |
+               (var->sync & FB_SYNC_HOR_HIGH_ACT ?
+                LCCR3_HorSnchH : LCCR3_HorSnchL) |
+               (var->sync & FB_SYNC_VERT_HIGH_ACT ?
+                LCCR3_VrtSnchH : LCCR3_VrtSnchL);
+
+       if (pcd) {
+               fbi->reg_lccr3 |= LCCR3_PixClkDiv(pcd);
+               set_hsync_time(fbi, pcd);
+       }
+}
 
-       if (pcd)
-               new_regs.lccr3 |= LCCR3_PixClkDiv(pcd);
+/*
+ * pxafb_activate_var():
+ *     Configures LCD Controller based on entries in var parameter.
+ *     Settings are only written to the controller if changes were made.
+ */
+static int pxafb_activate_var(struct fb_var_screeninfo *var,
+                             struct pxafb_info *fbi)
+{
+       u_long flags;
+       size_t nbytes;
 
-       pr_debug("nlccr0 = 0x%08x\n", new_regs.lccr0);
-       pr_debug("nlccr1 = 0x%08x\n", new_regs.lccr1);
-       pr_debug("nlccr2 = 0x%08x\n", new_regs.lccr2);
-       pr_debug("nlccr3 = 0x%08x\n", new_regs.lccr3);
+#if DEBUG_VAR
+       if (!(fbi->lccr0 & LCCR0_LCDT)) {
+               if (var->xres < 16 || var->xres > 1024)
+                       printk(KERN_ERR "%s: invalid xres %d\n",
+                               fbi->fb.fix.id, var->xres);
+               switch (var->bits_per_pixel) {
+               case 1:
+               case 2:
+               case 4:
+               case 8:
+               case 16:
+                       break;
+               default:
+                       printk(KERN_ERR "%s: invalid bit depth %d\n",
+                              fbi->fb.fix.id, var->bits_per_pixel);
+                       break;
+               }
 
+               if (var->hsync_len < 1 || var->hsync_len > 64)
+                       printk(KERN_ERR "%s: invalid hsync_len %d\n",
+                               fbi->fb.fix.id, var->hsync_len);
+               if (var->left_margin < 1 || var->left_margin > 255)
+                       printk(KERN_ERR "%s: invalid left_margin %d\n",
+                               fbi->fb.fix.id, var->left_margin);
+               if (var->right_margin < 1 || var->right_margin > 255)
+                       printk(KERN_ERR "%s: invalid right_margin %d\n",
+                               fbi->fb.fix.id, var->right_margin);
+               if (var->yres < 1 || var->yres > 1024)
+                       printk(KERN_ERR "%s: invalid yres %d\n",
+                               fbi->fb.fix.id, var->yres);
+               if (var->vsync_len < 1 || var->vsync_len > 64)
+                       printk(KERN_ERR "%s: invalid vsync_len %d\n",
+                               fbi->fb.fix.id, var->vsync_len);
+               if (var->upper_margin < 0 || var->upper_margin > 255)
+                       printk(KERN_ERR "%s: invalid upper_margin %d\n",
+                               fbi->fb.fix.id, var->upper_margin);
+               if (var->lower_margin < 0 || var->lower_margin > 255)
+                       printk(KERN_ERR "%s: invalid lower_margin %d\n",
+                               fbi->fb.fix.id, var->lower_margin);
+       }
+#endif
        /* Update shadow copy atomically */
        local_irq_save(flags);
 
-       /* setup dma descriptors */
-       fbi->dmadesc_fblow_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 3*16);
-       fbi->dmadesc_fbhigh_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 2*16);
-       fbi->dmadesc_palette_cpu = (struct pxafb_dma_descriptor *)((unsigned int)fbi->palette_cpu - 1*16);
-
-       fbi->dmadesc_fblow_dma = fbi->palette_dma - 3*16;
-       fbi->dmadesc_fbhigh_dma = fbi->palette_dma - 2*16;
-       fbi->dmadesc_palette_dma = fbi->palette_dma - 1*16;
-
-#define BYTES_PER_PANEL (lines_per_panel * fbi->fb.fix.line_length)
-
-       /* populate descriptors */
-       fbi->dmadesc_fblow_cpu->fdadr = fbi->dmadesc_fblow_dma;
-       fbi->dmadesc_fblow_cpu->fsadr = fbi->screen_dma + BYTES_PER_PANEL;
-       fbi->dmadesc_fblow_cpu->fidr  = 0;
-       fbi->dmadesc_fblow_cpu->ldcmd = BYTES_PER_PANEL;
+#ifdef CONFIG_FB_PXA_SMARTPANEL
+       if (fbi->lccr0 & LCCR0_LCDT)
+               setup_smart_timing(fbi, var);
+       else
+#endif
+               setup_parallel_timing(fbi, var);
 
-       fbi->fdadr1 = fbi->dmadesc_fblow_dma; /* only used in dual-panel mode */
+       fbi->reg_lccr0 = fbi->lccr0 |
+               (LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM |
+                LCCR0_QDM | LCCR0_BM  | LCCR0_OUM);
 
-       fbi->dmadesc_fbhigh_cpu->fsadr = fbi->screen_dma;
-       fbi->dmadesc_fbhigh_cpu->fidr = 0;
-       fbi->dmadesc_fbhigh_cpu->ldcmd = BYTES_PER_PANEL;
+       fbi->reg_lccr3 |= pxafb_bpp_to_lccr3(var);
 
-       fbi->dmadesc_palette_cpu->fsadr = fbi->palette_dma;
-       fbi->dmadesc_palette_cpu->fidr  = 0;
-       if ((fbi->lccr4 & LCCR4_PAL_FOR_MASK) == LCCR4_PAL_FOR_0)
-               fbi->dmadesc_palette_cpu->ldcmd = fbi->palette_size *
-                                                       sizeof(u16);
-       else
-               fbi->dmadesc_palette_cpu->ldcmd = fbi->palette_size *
-                                                       sizeof(u32);
-       fbi->dmadesc_palette_cpu->ldcmd |= LDCMD_PAL;
+       nbytes = var->yres * fbi->fb.fix.line_length;
 
-       if (var->bits_per_pixel == 16) {
-               /* palette shouldn't be loaded in true-color mode */
-               fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_fbhigh_dma;
-               fbi->fdadr0 = fbi->dmadesc_fbhigh_dma; /* no pal just fbhigh */
-               /* init it to something, even though we won't be using it */
-               fbi->dmadesc_palette_cpu->fdadr = fbi->dmadesc_palette_dma;
-       } else {
-               fbi->dmadesc_palette_cpu->fdadr = fbi->dmadesc_fbhigh_dma;
-               fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_palette_dma;
-               fbi->fdadr0 = fbi->dmadesc_palette_dma; /* flips back and forth between pal and fbhigh */
+       if ((fbi->lccr0 & LCCR0_SDS) == LCCR0_Dual) {
+               nbytes = nbytes / 2;
+               setup_frame_dma(fbi, DMA_LOWER, PAL_NONE, nbytes, nbytes);
        }
 
-#if 0
-       pr_debug("fbi->dmadesc_fblow_cpu = 0x%p\n", fbi->dmadesc_fblow_cpu);
-       pr_debug("fbi->dmadesc_fbhigh_cpu = 0x%p\n", fbi->dmadesc_fbhigh_cpu);
-       pr_debug("fbi->dmadesc_palette_cpu = 0x%p\n", fbi->dmadesc_palette_cpu);
-       pr_debug("fbi->dmadesc_fblow_dma = 0x%x\n", fbi->dmadesc_fblow_dma);
-       pr_debug("fbi->dmadesc_fbhigh_dma = 0x%x\n", fbi->dmadesc_fbhigh_dma);
-       pr_debug("fbi->dmadesc_palette_dma = 0x%x\n", fbi->dmadesc_palette_dma);
-
-       pr_debug("fbi->dmadesc_fblow_cpu->fdadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fdadr);
-       pr_debug("fbi->dmadesc_fbhigh_cpu->fdadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fdadr);
-       pr_debug("fbi->dmadesc_palette_cpu->fdadr = 0x%x\n", fbi->dmadesc_palette_cpu->fdadr);
-
-       pr_debug("fbi->dmadesc_fblow_cpu->fsadr = 0x%x\n", fbi->dmadesc_fblow_cpu->fsadr);
-       pr_debug("fbi->dmadesc_fbhigh_cpu->fsadr = 0x%x\n", fbi->dmadesc_fbhigh_cpu->fsadr);
-       pr_debug("fbi->dmadesc_palette_cpu->fsadr = 0x%x\n", fbi->dmadesc_palette_cpu->fsadr);
-
-       pr_debug("fbi->dmadesc_fblow_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fblow_cpu->ldcmd);
-       pr_debug("fbi->dmadesc_fbhigh_cpu->ldcmd = 0x%x\n", fbi->dmadesc_fbhigh_cpu->ldcmd);
-       pr_debug("fbi->dmadesc_palette_cpu->ldcmd = 0x%x\n", fbi->dmadesc_palette_cpu->ldcmd);
-#endif
+       if ((var->bits_per_pixel >= 16) || (fbi->lccr0 & LCCR0_LCDT))
+               setup_frame_dma(fbi, DMA_BASE, PAL_NONE, 0, nbytes);
+       else
+               setup_frame_dma(fbi, DMA_BASE, PAL_BASE, 0, nbytes);
 
-       fbi->reg_lccr0 = new_regs.lccr0;
-       fbi->reg_lccr1 = new_regs.lccr1;
-       fbi->reg_lccr2 = new_regs.lccr2;
-       fbi->reg_lccr3 = new_regs.lccr3;
-       fbi->reg_lccr4 = LCCR4 & (~LCCR4_PAL_FOR_MASK);
+       fbi->reg_lccr4 = lcd_readl(fbi, LCCR4) & ~LCCR4_PAL_FOR_MASK;
        fbi->reg_lccr4 |= (fbi->lccr4 & LCCR4_PAL_FOR_MASK);
-       set_hsync_time(fbi, pcd);
        local_irq_restore(flags);
 
        /*
         * Only update the registers if the controller is enabled
         * and something has changed.
         */
-       if ((LCCR0  != fbi->reg_lccr0) || (LCCR1  != fbi->reg_lccr1) ||
-           (LCCR2  != fbi->reg_lccr2) || (LCCR3  != fbi->reg_lccr3) ||
-           (FDADR0 != fbi->fdadr0)    || (FDADR1 != fbi->fdadr1))
+       if ((lcd_readl(fbi, LCCR0) != fbi->reg_lccr0) ||
+           (lcd_readl(fbi, LCCR1) != fbi->reg_lccr1) ||
+           (lcd_readl(fbi, LCCR2) != fbi->reg_lccr2) ||
+           (lcd_readl(fbi, LCCR3) != fbi->reg_lccr3) ||
+           (lcd_readl(fbi, FDADR0) != fbi->fdadr[0]) ||
+           (lcd_readl(fbi, FDADR1) != fbi->fdadr[1]))
                pxafb_schedule_work(fbi, C_REENABLE);
 
        return 0;
@@ -773,8 +919,8 @@ static inline void __pxafb_backlight_power(struct pxafb_info *fbi, int on)
 {
        pr_debug("pxafb: backlight o%s\n", on ? "n" : "ff");
 
-       if (pxafb_backlight_power)
-               pxafb_backlight_power(on);
+       if (pxafb_backlight_power)
+               pxafb_backlight_power(on);
 }
 
 static inline void __pxafb_lcd_power(struct pxafb_info *fbi, int on)
@@ -788,11 +934,11 @@ static inline void __pxafb_lcd_power(struct pxafb_info *fbi, int on)
 static void pxafb_setup_gpio(struct pxafb_info *fbi)
 {
        int gpio, ldd_bits;
-        unsigned int lccr0 = fbi->lccr0;
+       unsigned int lccr0 = fbi->lccr0;
 
        /*
         * setup is based on type of panel supported
-        */
+        */
 
        /* 4 bit interface */
        if ((lccr0 & LCCR0_CMS) == LCCR0_Mono &&
@@ -801,21 +947,25 @@ static void pxafb_setup_gpio(struct pxafb_info *fbi)
                ldd_bits = 4;
 
        /* 8 bit interface */
-        else if (((lccr0 & LCCR0_CMS) == LCCR0_Mono &&
-                 ((lccr0 & LCCR0_SDS) == LCCR0_Dual || (lccr0 & LCCR0_DPD) == LCCR0_8PixMono)) ||
-                 ((lccr0 & LCCR0_CMS) == LCCR0_Color &&
-                 (lccr0 & LCCR0_PAS) == LCCR0_Pas && (lccr0 & LCCR0_SDS) == LCCR0_Sngl))
+       else if (((lccr0 & LCCR0_CMS) == LCCR0_Mono &&
+                 ((lccr0 & LCCR0_SDS) == LCCR0_Dual ||
+                  (lccr0 & LCCR0_DPD) == LCCR0_8PixMono)) ||
+                ((lccr0 & LCCR0_CMS) == LCCR0_Color &&
+                 (lccr0 & LCCR0_PAS) == LCCR0_Pas &&
+                 (lccr0 & LCCR0_SDS) == LCCR0_Sngl))
                ldd_bits = 8;
 
        /* 16 bit interface */
        else if ((lccr0 & LCCR0_CMS) == LCCR0_Color &&
-                ((lccr0 & LCCR0_SDS) == LCCR0_Dual || (lccr0 & LCCR0_PAS) == LCCR0_Act))
+                ((lccr0 & LCCR0_SDS) == LCCR0_Dual ||
+                 (lccr0 & LCCR0_PAS) == LCCR0_Act))
                ldd_bits = 16;
 
        else {
-               printk(KERN_ERR "pxafb_setup_gpio: unable to determine bits per pixel\n");
+               printk(KERN_ERR "pxafb_setup_gpio: unable to determine "
+                              "bits per pixel\n");
                return;
-        }
+       }
 
        for (gpio = 58; ldd_bits; gpio++, ldd_bits--)
                pxa_gpio_mode(gpio | GPIO_ALT_FN_2_OUT);
@@ -828,8 +978,8 @@ static void pxafb_setup_gpio(struct pxafb_info *fbi)
 static void pxafb_enable_controller(struct pxafb_info *fbi)
 {
        pr_debug("pxafb: Enabling LCD controller\n");
-       pr_debug("fdadr0 0x%08x\n", (unsigned int) fbi->fdadr0);
-       pr_debug("fdadr1 0x%08x\n", (unsigned int) fbi->fdadr1);
+       pr_debug("fdadr0 0x%08x\n", (unsigned int) fbi->fdadr[0]);
+       pr_debug("fdadr1 0x%08x\n", (unsigned int) fbi->fdadr[1]);
        pr_debug("reg_lccr0 0x%08x\n", (unsigned int) fbi->reg_lccr0);
        pr_debug("reg_lccr1 0x%08x\n", (unsigned int) fbi->reg_lccr1);
        pr_debug("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2);
@@ -838,40 +988,40 @@ static void pxafb_enable_controller(struct pxafb_info *fbi)
        /* enable LCD controller clock */
        clk_enable(fbi->clk);
 
+       if (fbi->lccr0 & LCCR0_LCDT)
+               return;
+
        /* Sequence from 11.7.10 */
-       LCCR3 = fbi->reg_lccr3;
-       LCCR2 = fbi->reg_lccr2;
-       LCCR1 = fbi->reg_lccr1;
-       LCCR0 = fbi->reg_lccr0 & ~LCCR0_ENB;
-
-       FDADR0 = fbi->fdadr0;
-       FDADR1 = fbi->fdadr1;
-       LCCR0 |= LCCR0_ENB;
-
-       pr_debug("FDADR0 0x%08x\n", (unsigned int) FDADR0);
-       pr_debug("FDADR1 0x%08x\n", (unsigned int) FDADR1);
-       pr_debug("LCCR0 0x%08x\n", (unsigned int) LCCR0);
-       pr_debug("LCCR1 0x%08x\n", (unsigned int) LCCR1);
-       pr_debug("LCCR2 0x%08x\n", (unsigned int) LCCR2);
-       pr_debug("LCCR3 0x%08x\n", (unsigned int) LCCR3);
-       pr_debug("LCCR4 0x%08x\n", (unsigned int) LCCR4);
+       lcd_writel(fbi, LCCR3, fbi->reg_lccr3);
+       lcd_writel(fbi, LCCR2, fbi->reg_lccr2);
+       lcd_writel(fbi, LCCR1, fbi->reg_lccr1);
+       lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB);
+
+       lcd_writel(fbi, FDADR0, fbi->fdadr[0]);
+       lcd_writel(fbi, FDADR1, fbi->fdadr[1]);
+       lcd_writel(fbi, LCCR0, fbi->reg_lccr0 | LCCR0_ENB);
 }
 
 static void pxafb_disable_controller(struct pxafb_info *fbi)
 {
-       DECLARE_WAITQUEUE(wait, current);
+       uint32_t lccr0;
 
-       pr_debug("pxafb: disabling LCD controller\n");
+#ifdef CONFIG_FB_PXA_SMARTPANEL
+       if (fbi->lccr0 & LCCR0_LCDT) {
+               wait_for_completion_timeout(&fbi->refresh_done,
+                               200 * HZ / 1000);
+               return;
+       }
+#endif
 
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       add_wait_queue(&fbi->ctrlr_wait, &wait);
+       /* Clear LCD Status Register */
+       lcd_writel(fbi, LCSR, 0xffffffff);
 
-       LCSR = 0xffffffff;      /* Clear LCD Status Register */
-       LCCR0 &= ~LCCR0_LDM;    /* Enable LCD Disable Done Interrupt */
-       LCCR0 |= LCCR0_DIS;     /* Disable LCD Controller */
+       lccr0 = lcd_readl(fbi, LCCR0) & ~LCCR0_LDM;
+       lcd_writel(fbi, LCCR0, lccr0);
+       lcd_writel(fbi, LCCR0, lccr0 | LCCR0_DIS);
 
-       schedule_timeout(200 * HZ / 1000);
-       remove_wait_queue(&fbi->ctrlr_wait, &wait);
+       wait_for_completion_timeout(&fbi->disable_done, 200 * HZ / 1000);
 
        /* disable LCD controller clock */
        clk_disable(fbi->clk);
@@ -883,14 +1033,20 @@ static void pxafb_disable_controller(struct pxafb_info *fbi)
 static irqreturn_t pxafb_handle_irq(int irq, void *dev_id)
 {
        struct pxafb_info *fbi = dev_id;
-       unsigned int lcsr = LCSR;
+       unsigned int lccr0, lcsr = lcd_readl(fbi, LCSR);
 
        if (lcsr & LCSR_LDD) {
-               LCCR0 |= LCCR0_LDM;
-               wake_up(&fbi->ctrlr_wait);
+               lccr0 = lcd_readl(fbi, LCCR0);
+               lcd_writel(fbi, LCCR0, lccr0 | LCCR0_LDM);
+               complete(&fbi->disable_done);
        }
 
-       LCSR = lcsr;
+#ifdef CONFIG_FB_PXA_SMARTPANEL
+       if (lcsr & LCSR_CMD_INT)
+               complete(&fbi->command_done);
+#endif
+
+       lcd_writel(fbi, LCSR, lcsr);
        return IRQ_HANDLED;
 }
 
@@ -921,7 +1077,7 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
                 */
                if (old_state != C_DISABLE && old_state != C_DISABLE_PM) {
                        fbi->state = state;
-                       //TODO __pxafb_lcd_power(fbi, 0);
+                       /* TODO __pxafb_lcd_power(fbi, 0); */
                        pxafb_disable_controller(fbi);
                }
                break;
@@ -948,7 +1104,7 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
                if (old_state == C_DISABLE_CLKCHANGE) {
                        fbi->state = C_ENABLE;
                        pxafb_enable_controller(fbi);
-                       //TODO __pxafb_lcd_power(fbi, 1);
+                       /* TODO __pxafb_lcd_power(fbi, 1); */
                }
                break;
 
@@ -1019,7 +1175,7 @@ static int
 pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data)
 {
        struct pxafb_info *fbi = TO_INF(nb, freq_transition);
-       //TODO struct cpufreq_freqs *f = data;
+       /* TODO struct cpufreq_freqs *f = data; */
        u_int pcd;
 
        switch (val) {
@@ -1030,7 +1186,8 @@ pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data)
        case CPUFREQ_POSTCHANGE:
                pcd = get_pcd(fbi, fbi->fb.var.pixclock);
                set_hsync_time(fbi, pcd);
-               fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
+               fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) |
+                                 LCCR3_PixClkDiv(pcd);
                set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
                break;
        }
@@ -1050,18 +1207,8 @@ pxafb_freq_policy(struct notifier_block *nb, unsigned long val, void *data)
                pr_debug("min dma period: %d ps, "
                        "new clock %d kHz\n", pxafb_display_dma_period(var),
                        policy->max);
-               // TODO: fill in min/max values
-               break;
-#if 0
-       case CPUFREQ_NOTIFY:
-               printk(KERN_ERR "%s: got CPUFREQ_NOTIFY\n", __FUNCTION__);
-               do {} while(0);
-               /* todo: panic if min/max values aren't fulfilled
-                * [can't really happen unless there's a bug in the
-                * CPU policy verification process *
-                */
+               /* TODO: fill in min/max values */
                break;
-#endif
        }
        return 0;
 }
@@ -1102,21 +1249,21 @@ static int pxafb_resume(struct platform_device *dev)
  */
 static int __init pxafb_map_video_memory(struct pxafb_info *fbi)
 {
-       u_long palette_mem_size;
-
        /*
         * We reserve one page for the palette, plus the size
         * of the framebuffer.
         */
-       fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
+       fbi->video_offset = PAGE_ALIGN(sizeof(struct pxafb_dma_buff));
+       fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + fbi->video_offset);
        fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size,
                                              &fbi->map_dma, GFP_KERNEL);
 
        if (fbi->map_cpu) {
                /* prevent initial garbage on screen */
                memset(fbi->map_cpu, 0, fbi->map_size);
-               fbi->fb.screen_base = fbi->map_cpu + PAGE_SIZE;
-               fbi->screen_dma = fbi->map_dma + PAGE_SIZE;
+               fbi->fb.screen_base = fbi->map_cpu + fbi->video_offset;
+               fbi->screen_dma = fbi->map_dma + fbi->video_offset;
+
                /*
                 * FIXME: this is actually the wrong thing to place in
                 * smem_start.  But fbdev suffers from the problem that
@@ -1126,27 +1273,86 @@ static int __init pxafb_map_video_memory(struct pxafb_info *fbi)
                fbi->fb.fix.smem_start = fbi->screen_dma;
                fbi->palette_size = fbi->fb.var.bits_per_pixel == 8 ? 256 : 16;
 
-               if ((fbi->lccr4 & LCCR4_PAL_FOR_MASK) == LCCR4_PAL_FOR_0)
-                       palette_mem_size = fbi->palette_size * sizeof(u16);
-               else
-                       palette_mem_size = fbi->palette_size * sizeof(u32);
+               fbi->dma_buff = (void *) fbi->map_cpu;
+               fbi->dma_buff_phys = fbi->map_dma;
+               fbi->palette_cpu = (u16 *) fbi->dma_buff->palette;
 
-               pr_debug("pxafb: palette_mem_size = 0x%08lx\n", palette_mem_size);
-
-               fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
-               fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
+#ifdef CONFIG_FB_PXA_SMARTPANEL
+               fbi->smart_cmds = (uint16_t *) fbi->dma_buff->cmd_buff;
+               fbi->n_smart_cmds = 0;
+#endif
        }
 
        return fbi->map_cpu ? 0 : -ENOMEM;
 }
 
+static void pxafb_decode_mode_info(struct pxafb_info *fbi,
+                                  struct pxafb_mode_info *modes,
+                                  unsigned int num_modes)
+{
+       unsigned int i, smemlen;
+
+       pxafb_setmode(&fbi->fb.var, &modes[0]);
+
+       for (i = 0; i < num_modes; i++) {
+               smemlen = modes[i].xres * modes[i].yres * modes[i].bpp / 8;
+               if (smemlen > fbi->fb.fix.smem_len)
+                       fbi->fb.fix.smem_len = smemlen;
+       }
+}
+
+static int pxafb_decode_mach_info(struct pxafb_info *fbi,
+                                 struct pxafb_mach_info *inf)
+{
+       unsigned int lcd_conn = inf->lcd_conn;
+
+       fbi->cmap_inverse       = inf->cmap_inverse;
+       fbi->cmap_static        = inf->cmap_static;
+
+       switch (lcd_conn & 0xf) {
+       case LCD_TYPE_MONO_STN:
+               fbi->lccr0 = LCCR0_CMS;
+               break;
+       case LCD_TYPE_MONO_DSTN:
+               fbi->lccr0 = LCCR0_CMS | LCCR0_SDS;
+               break;
+       case LCD_TYPE_COLOR_STN:
+               fbi->lccr0 = 0;
+               break;
+       case LCD_TYPE_COLOR_DSTN:
+               fbi->lccr0 = LCCR0_SDS;
+               break;
+       case LCD_TYPE_COLOR_TFT:
+               fbi->lccr0 = LCCR0_PAS;
+               break;
+       case LCD_TYPE_SMART_PANEL:
+               fbi->lccr0 = LCCR0_LCDT | LCCR0_PAS;
+               break;
+       default:
+               /* fall back to backward compatibility way */
+               fbi->lccr0 = inf->lccr0;
+               fbi->lccr3 = inf->lccr3;
+               fbi->lccr4 = inf->lccr4;
+               return -EINVAL;
+       }
+
+       if (lcd_conn == LCD_MONO_STN_8BPP)
+               fbi->lccr0 |= LCCR0_DPD;
+
+       fbi->lccr3 = LCCR3_Acb((inf->lcd_conn >> 10) & 0xff);
+       fbi->lccr3 |= (lcd_conn & LCD_BIAS_ACTIVE_LOW) ? LCCR3_OEP : 0;
+       fbi->lccr3 |= (lcd_conn & LCD_PCLK_EDGE_FALL)  ? LCCR3_PCP : 0;
+
+       pxafb_decode_mode_info(fbi, inf->modes, inf->num_modes);
+       return 0;
+}
+
 static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
 {
        struct pxafb_info *fbi;
        void *addr;
        struct pxafb_mach_info *inf = dev->platform_data;
        struct pxafb_mode_info *mode = inf->modes;
-       int i, smemlen;
 
        /* Alloc the pxafb_info and pseudo_palette in one step */
        fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 16, GFP_KERNEL);
@@ -1186,187 +1392,233 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
        addr = addr + sizeof(struct pxafb_info);
        fbi->fb.pseudo_palette  = addr;
 
-       pxafb_setmode(&fbi->fb.var, mode);
+       fbi->state              = C_STARTUP;
+       fbi->task_state         = (u_char)-1;
 
-       fbi->cmap_inverse               = inf->cmap_inverse;
-       fbi->cmap_static                = inf->cmap_static;
-
-       fbi->lccr0                      = inf->lccr0;
-       fbi->lccr3                      = inf->lccr3;
-       fbi->lccr4                      = inf->lccr4;
-       fbi->state                      = C_STARTUP;
-       fbi->task_state                 = (u_char)-1;
-
-       for (i = 0; i < inf->num_modes; i++) {
-               smemlen = mode[i].xres * mode[i].yres * mode[i].bpp / 8;
-               if (smemlen > fbi->fb.fix.smem_len)
-                       fbi->fb.fix.smem_len = smemlen;
-       }
+       pxafb_decode_mach_info(fbi, inf);
 
        init_waitqueue_head(&fbi->ctrlr_wait);
        INIT_WORK(&fbi->task, pxafb_task);
        init_MUTEX(&fbi->ctrlr_sem);
+       init_completion(&fbi->disable_done);
+#ifdef CONFIG_FB_PXA_SMARTPANEL
+       init_completion(&fbi->command_done);
+       init_completion(&fbi->refresh_done);
+#endif
 
        return fbi;
 }
 
 #ifdef CONFIG_FB_PXA_PARAMETERS
-static int __init pxafb_parse_options(struct device *dev, char *options)
+static int __init parse_opt_mode(struct device *dev, const char *this_opt)
+{
+       struct pxafb_mach_info *inf = dev->platform_data;
+
+       const char *name = this_opt+5;
+       unsigned int namelen = strlen(name);
+       int res_specified = 0, bpp_specified = 0;
+       unsigned int xres = 0, yres = 0, bpp = 0;
+       int yres_specified = 0;
+       int i;
+       for (i = namelen-1; i >= 0; i--) {
+               switch (name[i]) {
+               case '-':
+                       namelen = i;
+                       if (!bpp_specified && !yres_specified) {
+                               bpp = simple_strtoul(&name[i+1], NULL, 0);
+                               bpp_specified = 1;
+                       } else
+                               goto done;
+                       break;
+               case 'x':
+                       if (!yres_specified) {
+                               yres = simple_strtoul(&name[i+1], NULL, 0);
+                               yres_specified = 1;
+                       } else
+                               goto done;
+                       break;
+               case '0' ... '9':
+                       break;
+               default:
+                       goto done;
+               }
+       }
+       if (i < 0 && yres_specified) {
+               xres = simple_strtoul(name, NULL, 0);
+               res_specified = 1;
+       }
+done:
+       if (res_specified) {
+               dev_info(dev, "overriding resolution: %dx%d\n", xres, yres);
+               inf->modes[0].xres = xres; inf->modes[0].yres = yres;
+       }
+       if (bpp_specified)
+               switch (bpp) {
+               case 1:
+               case 2:
+               case 4:
+               case 8:
+               case 16:
+                       inf->modes[0].bpp = bpp;
+                       dev_info(dev, "overriding bit depth: %d\n", bpp);
+                       break;
+               default:
+                       dev_err(dev, "Depth %d is not valid\n", bpp);
+                       return -EINVAL;
+               }
+       return 0;
+}
+
+static int __init parse_opt(struct device *dev, char *this_opt)
 {
        struct pxafb_mach_info *inf = dev->platform_data;
+       struct pxafb_mode_info *mode = &inf->modes[0];
+       char s[64];
+
+       s[0] = '\0';
+
+       if (!strncmp(this_opt, "mode:", 5)) {
+               return parse_opt_mode(dev, this_opt);
+       } else if (!strncmp(this_opt, "pixclock:", 9)) {
+               mode->pixclock = simple_strtoul(this_opt+9, NULL, 0);
+               sprintf(s, "pixclock: %ld\n", mode->pixclock);
+       } else if (!strncmp(this_opt, "left:", 5)) {
+               mode->left_margin = simple_strtoul(this_opt+5, NULL, 0);
+               sprintf(s, "left: %u\n", mode->left_margin);
+       } else if (!strncmp(this_opt, "right:", 6)) {
+               mode->right_margin = simple_strtoul(this_opt+6, NULL, 0);
+               sprintf(s, "right: %u\n", mode->right_margin);
+       } else if (!strncmp(this_opt, "upper:", 6)) {
+               mode->upper_margin = simple_strtoul(this_opt+6, NULL, 0);
+               sprintf(s, "upper: %u\n", mode->upper_margin);
+       } else if (!strncmp(this_opt, "lower:", 6)) {
+               mode->lower_margin = simple_strtoul(this_opt+6, NULL, 0);
+               sprintf(s, "lower: %u\n", mode->lower_margin);
+       } else if (!strncmp(this_opt, "hsynclen:", 9)) {
+               mode->hsync_len = simple_strtoul(this_opt+9, NULL, 0);
+               sprintf(s, "hsynclen: %u\n", mode->hsync_len);
+       } else if (!strncmp(this_opt, "vsynclen:", 9)) {
+               mode->vsync_len = simple_strtoul(this_opt+9, NULL, 0);
+               sprintf(s, "vsynclen: %u\n", mode->vsync_len);
+       } else if (!strncmp(this_opt, "hsync:", 6)) {
+               if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
+                       sprintf(s, "hsync: Active Low\n");
+                       mode->sync &= ~FB_SYNC_HOR_HIGH_ACT;
+               } else {
+                       sprintf(s, "hsync: Active High\n");
+                       mode->sync |= FB_SYNC_HOR_HIGH_ACT;
+               }
+       } else if (!strncmp(this_opt, "vsync:", 6)) {
+               if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
+                       sprintf(s, "vsync: Active Low\n");
+                       mode->sync &= ~FB_SYNC_VERT_HIGH_ACT;
+               } else {
+                       sprintf(s, "vsync: Active High\n");
+                       mode->sync |= FB_SYNC_VERT_HIGH_ACT;
+               }
+       } else if (!strncmp(this_opt, "dpc:", 4)) {
+               if (simple_strtoul(this_opt+4, NULL, 0) == 0) {
+                       sprintf(s, "double pixel clock: false\n");
+                       inf->lccr3 &= ~LCCR3_DPC;
+               } else {
+                       sprintf(s, "double pixel clock: true\n");
+                       inf->lccr3 |= LCCR3_DPC;
+               }
+       } else if (!strncmp(this_opt, "outputen:", 9)) {
+               if (simple_strtoul(this_opt+9, NULL, 0) == 0) {
+                       sprintf(s, "output enable: active low\n");
+                       inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnL;
+               } else {
+                       sprintf(s, "output enable: active high\n");
+                       inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnH;
+               }
+       } else if (!strncmp(this_opt, "pixclockpol:", 12)) {
+               if (simple_strtoul(this_opt+12, NULL, 0) == 0) {
+                       sprintf(s, "pixel clock polarity: falling edge\n");
+                       inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixFlEdg;
+               } else {
+                       sprintf(s, "pixel clock polarity: rising edge\n");
+                       inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixRsEdg;
+               }
+       } else if (!strncmp(this_opt, "color", 5)) {
+               inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Color;
+       } else if (!strncmp(this_opt, "mono", 4)) {
+               inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Mono;
+       } else if (!strncmp(this_opt, "active", 6)) {
+               inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Act;
+       } else if (!strncmp(this_opt, "passive", 7)) {
+               inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Pas;
+       } else if (!strncmp(this_opt, "single", 6)) {
+               inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Sngl;
+       } else if (!strncmp(this_opt, "dual", 4)) {
+               inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Dual;
+       } else if (!strncmp(this_opt, "4pix", 4)) {
+               inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_4PixMono;
+       } else if (!strncmp(this_opt, "8pix", 4)) {
+               inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_8PixMono;
+       } else {
+               dev_err(dev, "unknown option: %s\n", this_opt);
+               return -EINVAL;
+       }
+
+       if (s[0] != '\0')
+               dev_info(dev, "override %s", s);
+
+       return 0;
+}
+
+static int __init pxafb_parse_options(struct device *dev, char *options)
+{
        char *this_opt;
+       int ret;
 
-        if (!options || !*options)
-                return 0;
+       if (!options || !*options)
+               return 0;
 
        dev_dbg(dev, "options are \"%s\"\n", options ? options : "null");
 
        /* could be made table driven or similar?... */
-        while ((this_opt = strsep(&options, ",")) != NULL) {
-                if (!strncmp(this_opt, "mode:", 5)) {
-                       const char *name = this_opt+5;
-                       unsigned int namelen = strlen(name);
-                       int res_specified = 0, bpp_specified = 0;
-                       unsigned int xres = 0, yres = 0, bpp = 0;
-                       int yres_specified = 0;
-                       int i;
-                       for (i = namelen-1; i >= 0; i--) {
-                               switch (name[i]) {
-                               case '-':
-                                       namelen = i;
-                                       if (!bpp_specified && !yres_specified) {
-                                               bpp = simple_strtoul(&name[i+1], NULL, 0);
-                                               bpp_specified = 1;
-                                       } else
-                                               goto done;
-                                       break;
-                               case 'x':
-                                       if (!yres_specified) {
-                                               yres = simple_strtoul(&name[i+1], NULL, 0);
-                                               yres_specified = 1;
-                                       } else
-                                               goto done;
-                                       break;
-                               case '0' ... '9':
-                                       break;
-                               default:
-                                       goto done;
-                               }
-                       }
-                       if (i < 0 && yres_specified) {
-                               xres = simple_strtoul(name, NULL, 0);
-                               res_specified = 1;
-                       }
-               done:
-                       if (res_specified) {
-                               dev_info(dev, "overriding resolution: %dx%d\n", xres, yres);
-                               inf->modes[0].xres = xres; inf->modes[0].yres = yres;
-                       }
-                       if (bpp_specified)
-                               switch (bpp) {
-                               case 1:
-                               case 2:
-                               case 4:
-                               case 8:
-                               case 16:
-                                       inf->modes[0].bpp = bpp;
-                                       dev_info(dev, "overriding bit depth: %d\n", bpp);
-                                       break;
-                               default:
-                                       dev_err(dev, "Depth %d is not valid\n", bpp);
-                               }
-                } else if (!strncmp(this_opt, "pixclock:", 9)) {
-                        inf->modes[0].pixclock = simple_strtoul(this_opt+9, NULL, 0);
-                       dev_info(dev, "override pixclock: %ld\n", inf->modes[0].pixclock);
-                } else if (!strncmp(this_opt, "left:", 5)) {
-                        inf->modes[0].left_margin = simple_strtoul(this_opt+5, NULL, 0);
-                       dev_info(dev, "override left: %u\n", inf->modes[0].left_margin);
-                } else if (!strncmp(this_opt, "right:", 6)) {
-                        inf->modes[0].right_margin = simple_strtoul(this_opt+6, NULL, 0);
-                       dev_info(dev, "override right: %u\n", inf->modes[0].right_margin);
-                } else if (!strncmp(this_opt, "upper:", 6)) {
-                        inf->modes[0].upper_margin = simple_strtoul(this_opt+6, NULL, 0);
-                       dev_info(dev, "override upper: %u\n", inf->modes[0].upper_margin);
-                } else if (!strncmp(this_opt, "lower:", 6)) {
-                        inf->modes[0].lower_margin = simple_strtoul(this_opt+6, NULL, 0);
-                       dev_info(dev, "override lower: %u\n", inf->modes[0].lower_margin);
-                } else if (!strncmp(this_opt, "hsynclen:", 9)) {
-                        inf->modes[0].hsync_len = simple_strtoul(this_opt+9, NULL, 0);
-                       dev_info(dev, "override hsynclen: %u\n", inf->modes[0].hsync_len);
-                } else if (!strncmp(this_opt, "vsynclen:", 9)) {
-                        inf->modes[0].vsync_len = simple_strtoul(this_opt+9, NULL, 0);
-                       dev_info(dev, "override vsynclen: %u\n", inf->modes[0].vsync_len);
-                } else if (!strncmp(this_opt, "hsync:", 6)) {
-                        if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
-                               dev_info(dev, "override hsync: Active Low\n");
-                               inf->modes[0].sync &= ~FB_SYNC_HOR_HIGH_ACT;
-                       } else {
-                               dev_info(dev, "override hsync: Active High\n");
-                               inf->modes[0].sync |= FB_SYNC_HOR_HIGH_ACT;
-                       }
-                } else if (!strncmp(this_opt, "vsync:", 6)) {
-                        if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
-                               dev_info(dev, "override vsync: Active Low\n");
-                               inf->modes[0].sync &= ~FB_SYNC_VERT_HIGH_ACT;
-                       } else {
-                               dev_info(dev, "override vsync: Active High\n");
-                               inf->modes[0].sync |= FB_SYNC_VERT_HIGH_ACT;
-                       }
-                } else if (!strncmp(this_opt, "dpc:", 4)) {
-                        if (simple_strtoul(this_opt+4, NULL, 0) == 0) {
-                               dev_info(dev, "override double pixel clock: false\n");
-                               inf->lccr3 &= ~LCCR3_DPC;
-                       } else {
-                               dev_info(dev, "override double pixel clock: true\n");
-                               inf->lccr3 |= LCCR3_DPC;
-                       }
-                } else if (!strncmp(this_opt, "outputen:", 9)) {
-                        if (simple_strtoul(this_opt+9, NULL, 0) == 0) {
-                               dev_info(dev, "override output enable: active low\n");
-                               inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnL;
-                       } else {
-                               dev_info(dev, "override output enable: active high\n");
-                               inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnH;
-                       }
-                } else if (!strncmp(this_opt, "pixclockpol:", 12)) {
-                        if (simple_strtoul(this_opt+12, NULL, 0) == 0) {
-                               dev_info(dev, "override pixel clock polarity: falling edge\n");
-                               inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixFlEdg;
-                       } else {
-                               dev_info(dev, "override pixel clock polarity: rising edge\n");
-                               inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixRsEdg;
-                       }
-                } else if (!strncmp(this_opt, "color", 5)) {
-                       inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Color;
-                } else if (!strncmp(this_opt, "mono", 4)) {
-                       inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Mono;
-                } else if (!strncmp(this_opt, "active", 6)) {
-                       inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Act;
-                } else if (!strncmp(this_opt, "passive", 7)) {
-                       inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Pas;
-                } else if (!strncmp(this_opt, "single", 6)) {
-                       inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Sngl;
-                } else if (!strncmp(this_opt, "dual", 4)) {
-                       inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Dual;
-                } else if (!strncmp(this_opt, "4pix", 4)) {
-                       inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_4PixMono;
-                } else if (!strncmp(this_opt, "8pix", 4)) {
-                       inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_8PixMono;
-               } else {
-                       dev_err(dev, "unknown option: %s\n", this_opt);
-                       return -EINVAL;
-               }
-        }
-        return 0;
+       while ((this_opt = strsep(&options, ",")) != NULL) {
+               ret = parse_opt(dev, this_opt);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+static char g_options[256] __devinitdata = "";
 
+#ifndef CONFIG_MODULES
+static int __devinit pxafb_setup_options(void)
+{
+       char *options = NULL;
+
+       if (fb_get_options("pxafb", &options))
+               return -ENODEV;
+
+       if (options)
+               strlcpy(g_options, options, sizeof(g_options));
+
+       return 0;
 }
+#else
+#define pxafb_setup_options()          (0)
+
+module_param_string(options, g_options, sizeof(g_options), 0);
+MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)");
+#endif
+
+#else
+#define pxafb_parse_options(...)       (0)
+#define pxafb_setup_options()          (0)
 #endif
 
 static int __init pxafb_probe(struct platform_device *dev)
 {
        struct pxafb_info *fbi;
        struct pxafb_mach_info *inf;
-       int ret;
+       struct resource *r;
+       int irq, ret;
 
        dev_dbg(&dev->dev, "pxafb_probe\n");
 
@@ -1376,38 +1628,45 @@ static int __init pxafb_probe(struct platform_device *dev)
        if (!inf)
                goto failed;
 
-#ifdef CONFIG_FB_PXA_PARAMETERS
        ret = pxafb_parse_options(&dev->dev, g_options);
        if (ret < 0)
                goto failed;
-#endif
 
 #ifdef DEBUG_VAR
-        /* Check for various illegal bit-combinations. Currently only
+       /* Check for various illegal bit-combinations. Currently only
         * a warning is given. */
 
-        if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK)
-                dev_warn(&dev->dev, "machine LCCR0 setting contains illegal bits: %08x\n",
-                        inf->lccr0 & LCCR0_INVALID_CONFIG_MASK);
-        if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK)
-                dev_warn(&dev->dev, "machine LCCR3 setting contains illegal bits: %08x\n",
-                        inf->lccr3 & LCCR3_INVALID_CONFIG_MASK);
-        if (inf->lccr0 & LCCR0_DPD &&
+       if (inf->lccr0 & LCCR0_INVALID_CONFIG_MASK)
+               dev_warn(&dev->dev, "machine LCCR0 setting contains "
+                               "illegal bits: %08x\n",
+                       inf->lccr0 & LCCR0_INVALID_CONFIG_MASK);
+       if (inf->lccr3 & LCCR3_INVALID_CONFIG_MASK)
+               dev_warn(&dev->dev, "machine LCCR3 setting contains "
+                               "illegal bits: %08x\n",
+                       inf->lccr3 & LCCR3_INVALID_CONFIG_MASK);
+       if (inf->lccr0 & LCCR0_DPD &&
            ((inf->lccr0 & LCCR0_PAS) != LCCR0_Pas ||
             (inf->lccr0 & LCCR0_SDS) != LCCR0_Sngl ||
             (inf->lccr0 & LCCR0_CMS) != LCCR0_Mono))
-                dev_warn(&dev->dev, "Double Pixel Data (DPD) mode is only valid in passive mono"
-                        " single panel mode\n");
-        if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Act &&
+               dev_warn(&dev->dev, "Double Pixel Data (DPD) mode is "
+                               "only valid in passive mono"
+                               " single panel mode\n");
+       if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Act &&
            (inf->lccr0 & LCCR0_SDS) == LCCR0_Dual)
-                dev_warn(&dev->dev, "Dual panel only valid in passive mode\n");
-        if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas &&
-             (inf->modes->upper_margin || inf->modes->lower_margin))
-                dev_warn(&dev->dev, "Upper and lower margins must be 0 in passive mode\n");
+               dev_warn(&dev->dev, "Dual panel only valid in passive mode\n");
+       if ((inf->lccr0 & LCCR0_PAS) == LCCR0_Pas &&
+            (inf->modes->upper_margin || inf->modes->lower_margin))
+               dev_warn(&dev->dev, "Upper and lower margins must be 0 in "
+                               "passive mode\n");
 #endif
 
-       dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n",inf->modes->xres, inf->modes->yres, inf->modes->bpp);
-       if (inf->modes->xres == 0 || inf->modes->yres == 0 || inf->modes->bpp == 0) {
+       dev_dbg(&dev->dev, "got a %dx%dx%d LCD\n",
+                       inf->modes->xres,
+                       inf->modes->yres,
+                       inf->modes->bpp);
+       if (inf->modes->xres == 0 ||
+           inf->modes->yres == 0 ||
+           inf->modes->bpp == 0) {
                dev_err(&dev->dev, "Invalid resolution or bit depth\n");
                ret = -EINVAL;
                goto failed;
@@ -1416,26 +1675,62 @@ static int __init pxafb_probe(struct platform_device *dev)
        pxafb_lcd_power = inf->pxafb_lcd_power;
        fbi = pxafb_init_fbinfo(&dev->dev);
        if (!fbi) {
+               /* only reason for pxafb_init_fbinfo to fail is kmalloc */
                dev_err(&dev->dev, "Failed to initialize framebuffer device\n");
-               ret = -ENOMEM; // only reason for pxafb_init_fbinfo to fail is kmalloc
+               ret = -ENOMEM;
                goto failed;
        }
 
+       r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       if (r == NULL) {
+               dev_err(&dev->dev, "no I/O memory resource defined\n");
+               ret = -ENODEV;
+               goto failed;
+       }
+
+       r = request_mem_region(r->start, r->end - r->start + 1, dev->name);
+       if (r == NULL) {
+               dev_err(&dev->dev, "failed to request I/O memory\n");
+               ret = -EBUSY;
+               goto failed;
+       }
+
+       fbi->mmio_base = ioremap(r->start, r->end - r->start + 1);
+       if (fbi->mmio_base == NULL) {
+               dev_err(&dev->dev, "failed to map I/O memory\n");
+               ret = -EBUSY;
+               goto failed_free_res;
+       }
+
        /* Initialize video memory */
        ret = pxafb_map_video_memory(fbi);
        if (ret) {
                dev_err(&dev->dev, "Failed to allocate video RAM: %d\n", ret);
                ret = -ENOMEM;
-               goto failed;
+               goto failed_free_io;
+       }
+
+       irq = platform_get_irq(dev, 0);
+       if (irq < 0) {
+               dev_err(&dev->dev, "no IRQ defined\n");
+               ret = -ENODEV;
+               goto failed_free_mem;
        }
 
-       ret = request_irq(IRQ_LCD, pxafb_handle_irq, IRQF_DISABLED, "LCD", fbi);
+       ret = request_irq(irq, pxafb_handle_irq, IRQF_DISABLED, "LCD", fbi);
        if (ret) {
                dev_err(&dev->dev, "request_irq failed: %d\n", ret);
                ret = -EBUSY;
-               goto failed;
+               goto failed_free_mem;
        }
 
+#ifdef CONFIG_FB_PXA_SMARTPANEL
+       ret = pxafb_smart_init(fbi);
+       if (ret) {
+               dev_err(&dev->dev, "failed to initialize smartpanel\n");
+               goto failed_free_irq;
+       }
+#endif
        /*
         * This makes sure that our colour bitfield
         * descriptors are correctly initialised.
@@ -1447,19 +1742,18 @@ static int __init pxafb_probe(struct platform_device *dev)
 
        ret = register_framebuffer(&fbi->fb);
        if (ret < 0) {
-               dev_err(&dev->dev, "Failed to register framebuffer device: %d\n", ret);
-               goto failed;
+               dev_err(&dev->dev,
+                       "Failed to register framebuffer device: %d\n", ret);
+               goto failed_free_irq;
        }
 
-#ifdef CONFIG_PM
-       // TODO
-#endif
-
 #ifdef CONFIG_CPU_FREQ
        fbi->freq_transition.notifier_call = pxafb_freq_transition;
        fbi->freq_policy.notifier_call = pxafb_freq_policy;
-       cpufreq_register_notifier(&fbi->freq_transition, CPUFREQ_TRANSITION_NOTIFIER);
-       cpufreq_register_notifier(&fbi->freq_policy, CPUFREQ_POLICY_NOTIFIER);
+       cpufreq_register_notifier(&fbi->freq_transition,
+                               CPUFREQ_TRANSITION_NOTIFIER);
+       cpufreq_register_notifier(&fbi->freq_policy,
+                               CPUFREQ_POLICY_NOTIFIER);
 #endif
 
        /*
@@ -1469,6 +1763,15 @@ static int __init pxafb_probe(struct platform_device *dev)
 
        return 0;
 
+failed_free_irq:
+       free_irq(irq, fbi);
+failed_free_res:
+       release_mem_region(r->start, r->end - r->start + 1);
+failed_free_io:
+       iounmap(fbi->mmio_base);
+failed_free_mem:
+       dma_free_writecombine(&dev->dev, fbi->map_size,
+                       fbi->map_cpu, fbi->map_dma);
 failed:
        platform_set_drvdata(dev, NULL);
        kfree(fbi);
@@ -1477,40 +1780,18 @@ failed:
 
 static struct platform_driver pxafb_driver = {
        .probe          = pxafb_probe,
-#ifdef CONFIG_PM
        .suspend        = pxafb_suspend,
        .resume         = pxafb_resume,
-#endif
        .driver         = {
                .name   = "pxa2xx-fb",
        },
 };
 
-#ifndef MODULE
-static int __devinit pxafb_setup(char *options)
-{
-# ifdef CONFIG_FB_PXA_PARAMETERS
-       if (options)
-               strlcpy(g_options, options, sizeof(g_options));
-# endif
-       return 0;
-}
-#else
-# ifdef CONFIG_FB_PXA_PARAMETERS
-module_param_string(options, g_options, sizeof(g_options), 0);
-MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)");
-# endif
-#endif
-
 static int __devinit pxafb_init(void)
 {
-#ifndef MODULE
-       char *option = NULL;
+       if (pxafb_setup_options())
+               return -EINVAL;
 
-       if (fb_get_options("pxafb", &option))
-               return -ENODEV;
-       pxafb_setup(option);
-#endif
        return platform_driver_register(&pxafb_driver);
 }
 
index d920b8a14c35970c8f261ae41c2fc440cb815e38..8238dc8264297fb42c1b2b40226fb64edfb53c32 100644 (file)
  * for more details.
  */
 
-/* Shadows for LCD controller registers */
-struct pxafb_lcd_reg {
-       unsigned int lccr0;
-       unsigned int lccr1;
-       unsigned int lccr2;
-       unsigned int lccr3;
-};
-
 /* PXA LCD DMA descriptor */
 struct pxafb_dma_descriptor {
        unsigned int fdadr;
@@ -37,11 +29,49 @@ struct pxafb_dma_descriptor {
        unsigned int ldcmd;
 };
 
+enum {
+       PAL_NONE        = -1,
+       PAL_BASE        = 0,
+       PAL_OV1         = 1,
+       PAL_OV2         = 2,
+       PAL_MAX,
+};
+
+enum {
+       DMA_BASE        = 0,
+       DMA_UPPER       = 0,
+       DMA_LOWER       = 1,
+       DMA_OV1         = 1,
+       DMA_OV2_Y       = 2,
+       DMA_OV2_Cb      = 3,
+       DMA_OV2_Cr      = 4,
+       DMA_CURSOR      = 5,
+       DMA_CMD         = 6,
+       DMA_MAX,
+};
+
+/* maximum palette size - 256 entries, each 4 bytes long */
+#define PALETTE_SIZE   (256 * 4)
+#define CMD_BUFF_SIZE  (1024 * 50)
+
+struct pxafb_dma_buff {
+       unsigned char palette[PAL_MAX * PALETTE_SIZE];
+       uint16_t cmd_buff[CMD_BUFF_SIZE];
+       struct pxafb_dma_descriptor pal_desc[PAL_MAX];
+       struct pxafb_dma_descriptor dma_desc[DMA_MAX];
+};
+
 struct pxafb_info {
        struct fb_info          fb;
        struct device           *dev;
        struct clk              *clk;
 
+       void __iomem            *mmio_base;
+
+       struct pxafb_dma_buff   *dma_buff;
+       dma_addr_t              dma_buff_phys;
+       dma_addr_t              fdadr[DMA_MAX];
+
        /*
         * These are the addresses we mapped
         * the framebuffer memory region to.
@@ -55,19 +85,8 @@ struct pxafb_info {
        u_char *                screen_cpu;     /* virtual address of frame buffer */
        dma_addr_t              screen_dma;     /* physical address of frame buffer */
        u16 *                   palette_cpu;    /* virtual address of palette memory */
-       dma_addr_t              palette_dma;    /* physical address of palette memory */
        u_int                   palette_size;
-
-       /* DMA descriptors */
-       struct pxafb_dma_descriptor *   dmadesc_fblow_cpu;
-       dma_addr_t              dmadesc_fblow_dma;
-       struct pxafb_dma_descriptor *   dmadesc_fbhigh_cpu;
-       dma_addr_t              dmadesc_fbhigh_dma;
-       struct pxafb_dma_descriptor *   dmadesc_palette_cpu;
-       dma_addr_t              dmadesc_palette_dma;
-
-       dma_addr_t              fdadr0;
-       dma_addr_t              fdadr1;
+       ssize_t                 video_offset;
 
        u_int                   lccr0;
        u_int                   lccr3;
@@ -81,6 +100,7 @@ struct pxafb_info {
        u_int                   reg_lccr2;
        u_int                   reg_lccr3;
        u_int                   reg_lccr4;
+       u_int                   reg_cmdcr;
 
        unsigned long   hsync_time;
 
@@ -90,6 +110,16 @@ struct pxafb_info {
        wait_queue_head_t       ctrlr_wait;
        struct work_struct      task;
 
+       struct completion       disable_done;
+
+#ifdef CONFIG_FB_PXA_SMARTPANEL
+       uint16_t                *smart_cmds;
+       size_t                  n_smart_cmds;
+       struct completion       command_done;
+       struct completion       refresh_done;
+       struct task_struct      *smart_thread;
+#endif
+
 #ifdef CONFIG_CPU_FREQ
        struct notifier_block   freq_transition;
        struct notifier_block   freq_policy;
index fe6bdf43380f1cd95fea955ec583f4aceaa780fa..e6ab7cf08f8885d07cbfa222420d5c621c6039c3 100644 (file)
@@ -30,7 +30,7 @@
 #  define assert(expr) \
         if(unlikely(!(expr))) {                                        \
         printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n",        \
-        #expr,__FILE__,__FUNCTION__,__LINE__);                 \
+       #expr, __FILE__, __func__, __LINE__);                   \
         }
 #endif
 
index 2ce4cebc31d9d47e6465783a0fd11b06082ee7e9..099b6fb5b5cbd364817776edf8cc68129fe482df 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/types.h>
 #include <linux/zorro.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
 #include <asm/uaccess.h>
@@ -76,36 +77,58 @@ proc_bus_zorro_read(struct file *file, char __user *buf, size_t nbytes, loff_t *
 }
 
 static const struct file_operations proc_bus_zorro_operations = {
+       .owner          = THIS_MODULE,
        .llseek         = proc_bus_zorro_lseek,
        .read           = proc_bus_zorro_read,
 };
 
-static int
-get_zorro_dev_info(char *buf, char **start, off_t pos, int count)
+static void * zorro_seq_start(struct seq_file *m, loff_t *pos)
 {
-       u_int slot;
-       off_t at = 0;
-       int len, cnt;
-
-       for (slot = cnt = 0; slot < zorro_num_autocon && count > cnt; slot++) {
-               struct zorro_dev *z = &zorro_autocon[slot];
-               len = sprintf(buf, "%02x\t%08x\t%08lx\t%08lx\t%02x\n", slot,
-                             z->id, (unsigned long)zorro_resource_start(z),
-                             (unsigned long)zorro_resource_len(z),
-                             z->rom.er_Type);
-               at += len;
-               if (at >= pos) {
-                       if (!*start) {
-                               *start = buf + (pos - (at - len));
-                               cnt = at - pos;
-                       } else
-                               cnt += len;
-                       buf += len;
-               }
-       }
-       return (count > cnt) ? cnt : count;
+       return (*pos < zorro_num_autocon) ? pos : NULL;
+}
+
+static void * zorro_seq_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       (*pos)++;
+       return (*pos < zorro_num_autocon) ? pos : NULL;
+}
+
+static void zorro_seq_stop(struct seq_file *m, void *v)
+{
+}
+
+static int zorro_seq_show(struct seq_file *m, void *v)
+{
+       u_int slot = *(loff_t *)v;
+       struct zorro_dev *z = &zorro_autocon[slot];
+
+       seq_printf(m, "%02x\t%08x\t%08lx\t%08lx\t%02x\n", slot, z->id,
+                  (unsigned long)zorro_resource_start(z),
+                  (unsigned long)zorro_resource_len(z),
+                  z->rom.er_Type);
+       return 0;
+}
+
+static const struct seq_operations zorro_devices_seq_ops = {
+       .start = zorro_seq_start,
+       .next  = zorro_seq_next,
+       .stop  = zorro_seq_stop,
+       .show  = zorro_seq_show,
+};
+
+static int zorro_devices_proc_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &zorro_devices_seq_ops);
 }
 
+static const struct file_operations zorro_devices_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = zorro_devices_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
 static struct proc_dir_entry *proc_bus_zorro_dir;
 
 static int __init zorro_proc_attach_device(u_int slot)
@@ -114,11 +137,11 @@ static int __init zorro_proc_attach_device(u_int slot)
        char name[4];
 
        sprintf(name, "%02x", slot);
-       entry = create_proc_entry(name, 0, proc_bus_zorro_dir);
+       entry = proc_create_data(name, 0, proc_bus_zorro_dir,
+                                &proc_bus_zorro_operations,
+                                &zorro_autocon[slot]);
        if (!entry)
                return -ENOMEM;
-       entry->proc_fops = &proc_bus_zorro_operations;
-       entry->data = &zorro_autocon[slot];
        entry->size = sizeof(struct zorro_dev);
        return 0;
 }
@@ -128,9 +151,9 @@ static int __init zorro_proc_init(void)
        u_int slot;
 
        if (MACH_IS_AMIGA && AMIGAHW_PRESENT(ZORRO)) {
-               proc_bus_zorro_dir = proc_mkdir("zorro", proc_bus);
-               create_proc_info_entry("devices", 0, proc_bus_zorro_dir,
-                                      get_zorro_dev_info);
+               proc_bus_zorro_dir = proc_mkdir("bus/zorro", NULL);
+               proc_create("devices", 0, proc_bus_zorro_dir,
+                           &zorro_devices_proc_fops);
                for (slot = 0; slot < zorro_num_autocon; slot++)
                        zorro_proc_attach_device(slot);
        }
index 853845abcca676889bc854da217082de463e637a..55e8ee1900a5e9b2b2a9b4214be83561eafd5ebe 100644 (file)
@@ -41,7 +41,7 @@ config BINFMT_ELF_FDPIC
          It is also possible to run FDPIC ELF binaries on MMU linux also.
 
 config BINFMT_FLAT
-       tristate "Kernel support for flat binaries"
+       bool "Kernel support for flat binaries"
        depends on !MMU
        help
          Support uClinux FLAT format binaries.
index 936f2af39c433e12dfb8966b8716c3a90d7f1d2c..831157502d5ae58a25bcec65c9af58d5eabc871f 100644 (file)
@@ -75,7 +75,7 @@ extern unsigned int adfs_map_free(struct super_block *sb);
 /* Misc */
 void __adfs_error(struct super_block *sb, const char *function,
                  const char *fmt, ...);
-#define adfs_error(sb, fmt...) __adfs_error(sb, __FUNCTION__, fmt)
+#define adfs_error(sb, fmt...) __adfs_error(sb, __func__, fmt)
 
 /* super.c */
 
index b9b2b27b68c30f3dd97a7717d0f557e5f3f9615d..ea7df2146921142a27b4c27b5e4ebd15704f2f02 100644 (file)
@@ -122,9 +122,9 @@ adfs_dir_checkbyte(const struct adfs_dir *dir)
                ptr.ptr8 = bufoff(bh, i);
                end.ptr8 = ptr.ptr8 + last - i;
 
-               do
+               do {
                        dircheck = *ptr.ptr8++ ^ ror13(dircheck);
-               while (ptr.ptr8 < end.ptr8);
+               while (ptr.ptr8 < end.ptr8);
        }
 
        /*
index 6e0c9399200e84a74d163e25505d087487a2262d..1a4f092f24efdb2ab13efa4bebb85bd38e7d2678 100644 (file)
@@ -325,8 +325,7 @@ affs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_resul
        pr_debug("AFFS: get_block(%u, %lu)\n", (u32)inode->i_ino, (unsigned long)block);
 
 
-       if (block > (sector_t)0x7fffffffUL)
-               BUG();
+       BUG_ON(block > (sector_t)0x7fffffffUL);
 
        if (block >= AFFS_I(inode)->i_blkcnt) {
                if (block > AFFS_I(inode)->i_blkcnt || !create)
@@ -493,8 +492,7 @@ affs_do_readpage_ofs(struct file *file, struct page *page, unsigned from, unsign
        u32 tmp;
 
        pr_debug("AFFS: read_page(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to);
-       if (from > to || to > PAGE_CACHE_SIZE)
-               BUG();
+       BUG_ON(from > to || to > PAGE_CACHE_SIZE);
        kmap(page);
        data = page_address(page);
        bsize = AFFS_SB(sb)->s_data_blksize;
@@ -507,8 +505,7 @@ affs_do_readpage_ofs(struct file *file, struct page *page, unsigned from, unsign
                if (IS_ERR(bh))
                        return PTR_ERR(bh);
                tmp = min(bsize - boff, to - from);
-               if (from + tmp > to || tmp > bsize)
-                       BUG();
+               BUG_ON(from + tmp > to || tmp > bsize);
                memcpy(data + from, AFFS_DATA(bh) + boff, tmp);
                affs_brelse(bh);
                bidx++;
@@ -540,10 +537,9 @@ affs_extent_file_ofs(struct inode *inode, u32 newsize)
                if (IS_ERR(bh))
                        return PTR_ERR(bh);
                tmp = min(bsize - boff, newsize - size);
-               if (boff + tmp > bsize || tmp > bsize)
-                       BUG();
+               BUG_ON(boff + tmp > bsize || tmp > bsize);
                memset(AFFS_DATA(bh) + boff, 0, tmp);
-               AFFS_DATA_HEAD(bh)->size = cpu_to_be32(be32_to_cpu(AFFS_DATA_HEAD(bh)->size) + tmp);
+               be32_add_cpu(&AFFS_DATA_HEAD(bh)->size, tmp);
                affs_fix_checksum(sb, bh);
                mark_buffer_dirty_inode(bh, inode);
                size += tmp;
@@ -560,8 +556,7 @@ affs_extent_file_ofs(struct inode *inode, u32 newsize)
                if (IS_ERR(bh))
                        goto out;
                tmp = min(bsize, newsize - size);
-               if (tmp > bsize)
-                       BUG();
+               BUG_ON(tmp > bsize);
                AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
                AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);
                AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
@@ -683,10 +678,9 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
                if (IS_ERR(bh))
                        return PTR_ERR(bh);
                tmp = min(bsize - boff, to - from);
-               if (boff + tmp > bsize || tmp > bsize)
-                       BUG();
+               BUG_ON(boff + tmp > bsize || tmp > bsize);
                memcpy(AFFS_DATA(bh) + boff, data + from, tmp);
-               AFFS_DATA_HEAD(bh)->size = cpu_to_be32(be32_to_cpu(AFFS_DATA_HEAD(bh)->size) + tmp);
+               be32_add_cpu(&AFFS_DATA_HEAD(bh)->size, tmp);
                affs_fix_checksum(sb, bh);
                mark_buffer_dirty_inode(bh, inode);
                written += tmp;
@@ -732,8 +726,7 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
                if (IS_ERR(bh))
                        goto out;
                tmp = min(bsize, to - from);
-               if (tmp > bsize)
-                       BUG();
+               BUG_ON(tmp > bsize);
                memcpy(AFFS_DATA(bh), data + from, tmp);
                if (buffer_new(bh)) {
                        AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
index d2dc047cb4796b4a879606e60349ec4eb55a79ae..01d25d532541bc3d698f5321923a87cf9900cfe4 100644 (file)
@@ -199,7 +199,6 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s
                case Opt_prefix:
                        /* Free any previous prefix */
                        kfree(*prefix);
-                       *prefix = NULL;
                        *prefix = match_strdup(&args[0]);
                        if (!*prefix)
                                return 0;
@@ -233,6 +232,8 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s
                        break;
                case Opt_volume: {
                        char *vol = match_strdup(&args[0]);
+                       if (!vol)
+                               return 0;
                        strlcpy(volume, vol, 32);
                        kfree(vol);
                        break;
index 7b4d4fab4c80ed87d9aa687cbb3e9198b1b00e76..255f5dd6040c498d040753f3f88f30f726f61238 100644 (file)
@@ -24,7 +24,8 @@ enum AFS_CM_Operations {
        CBGetXStatsVersion      = 209,  /* get version of extended statistics */
        CBGetXStats             = 210,  /* get contents of extended statistics data */
        CBInitCallBackState3    = 213,  /* initialise callback state, version 3 */
-       CBGetCapabilities       = 65538, /* get client capabilities */
+       CBProbeUuid             = 214,  /* check the client hasn't rebooted */
+       CBTellMeAboutYourself   = 65538, /* get client capabilities */
 };
 
 #define AFS_CAP_ERROR_TRANSLATION      0x1
index 584bb0f9c36a35cdd5ed4234a83ba927e0d04e5e..5e1df14e16b188d9a47501a28c48ce65a4be4c5b 100644 (file)
@@ -20,7 +20,7 @@
 DECLARE_RWSEM(afs_proc_cells_sem);
 LIST_HEAD(afs_proc_cells);
 
-static struct list_head afs_cells = LIST_HEAD_INIT(afs_cells);
+static LIST_HEAD(afs_cells);
 static DEFINE_RWLOCK(afs_cells_lock);
 static DECLARE_RWSEM(afs_cells_sem); /* add/remove serialisation */
 static DECLARE_WAIT_QUEUE_HEAD(afs_cells_freeable_wq);
index 47b71c8947f91221ac9551b75a5dfa91810d2bd8..eb765489164f85c4c51d9ac1595a3b48e5d41cd2 100644 (file)
@@ -26,8 +26,9 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *,
                                                struct sk_buff *, bool);
 static int afs_deliver_cb_probe(struct afs_call *, struct sk_buff *, bool);
 static int afs_deliver_cb_callback(struct afs_call *, struct sk_buff *, bool);
-static int afs_deliver_cb_get_capabilities(struct afs_call *, struct sk_buff *,
-                                          bool);
+static int afs_deliver_cb_probe_uuid(struct afs_call *, struct sk_buff *, bool);
+static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *,
+                                                struct sk_buff *, bool);
 static void afs_cm_destructor(struct afs_call *);
 
 /*
@@ -71,11 +72,21 @@ static const struct afs_call_type afs_SRXCBProbe = {
 };
 
 /*
- * CB.GetCapabilities operation type
+ * CB.ProbeUuid operation type
  */
-static const struct afs_call_type afs_SRXCBGetCapabilites = {
-       .name           = "CB.GetCapabilities",
-       .deliver        = afs_deliver_cb_get_capabilities,
+static const struct afs_call_type afs_SRXCBProbeUuid = {
+       .name           = "CB.ProbeUuid",
+       .deliver        = afs_deliver_cb_probe_uuid,
+       .abort_to_error = afs_abort_to_error,
+       .destructor     = afs_cm_destructor,
+};
+
+/*
+ * CB.TellMeAboutYourself operation type
+ */
+static const struct afs_call_type afs_SRXCBTellMeAboutYourself = {
+       .name           = "CB.TellMeAboutYourself",
+       .deliver        = afs_deliver_cb_tell_me_about_yourself,
        .abort_to_error = afs_abort_to_error,
        .destructor     = afs_cm_destructor,
 };
@@ -103,8 +114,8 @@ bool afs_cm_incoming_call(struct afs_call *call)
        case CBProbe:
                call->type = &afs_SRXCBProbe;
                return true;
-       case CBGetCapabilities:
-               call->type = &afs_SRXCBGetCapabilites;
+       case CBTellMeAboutYourself:
+               call->type = &afs_SRXCBTellMeAboutYourself;
                return true;
        default:
                return false;
@@ -392,10 +403,106 @@ static int afs_deliver_cb_probe(struct afs_call *call, struct sk_buff *skb,
        return 0;
 }
 
+/*
+ * allow the fileserver to quickly find out if the fileserver has been rebooted
+ */
+static void SRXAFSCB_ProbeUuid(struct work_struct *work)
+{
+       struct afs_call *call = container_of(work, struct afs_call, work);
+       struct afs_uuid *r = call->request;
+
+       struct {
+               __be32  match;
+       } reply;
+
+       _enter("");
+
+
+       if (memcmp(r, &afs_uuid, sizeof(afs_uuid)) == 0)
+               reply.match = htonl(0);
+       else
+               reply.match = htonl(1);
+
+       afs_send_simple_reply(call, &reply, sizeof(reply));
+       _leave("");
+}
+
+/*
+ * deliver request data to a CB.ProbeUuid call
+ */
+static int afs_deliver_cb_probe_uuid(struct afs_call *call, struct sk_buff *skb,
+                                    bool last)
+{
+       struct afs_uuid *r;
+       unsigned loop;
+       __be32 *b;
+       int ret;
+
+       _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
+
+       if (skb->len > 0)
+               return -EBADMSG;
+       if (!last)
+               return 0;
+
+       switch (call->unmarshall) {
+       case 0:
+               call->offset = 0;
+               call->buffer = kmalloc(11 * sizeof(__be32), GFP_KERNEL);
+               if (!call->buffer)
+                       return -ENOMEM;
+               call->unmarshall++;
+
+       case 1:
+               _debug("extract UUID");
+               ret = afs_extract_data(call, skb, last, call->buffer,
+                                      11 * sizeof(__be32));
+               switch (ret) {
+               case 0:         break;
+               case -EAGAIN:   return 0;
+               default:        return ret;
+               }
+
+               _debug("unmarshall UUID");
+               call->request = kmalloc(sizeof(struct afs_uuid), GFP_KERNEL);
+               if (!call->request)
+                       return -ENOMEM;
+
+               b = call->buffer;
+               r = call->request;
+               r->time_low                     = ntohl(b[0]);
+               r->time_mid                     = ntohl(b[1]);
+               r->time_hi_and_version          = ntohl(b[2]);
+               r->clock_seq_hi_and_reserved    = ntohl(b[3]);
+               r->clock_seq_low                = ntohl(b[4]);
+
+               for (loop = 0; loop < 6; loop++)
+                       r->node[loop] = ntohl(b[loop + 5]);
+
+               call->offset = 0;
+               call->unmarshall++;
+
+       case 2:
+               _debug("trailer");
+               if (skb->len != 0)
+                       return -EBADMSG;
+               break;
+       }
+
+       if (!last)
+               return 0;
+
+       call->state = AFS_CALL_REPLYING;
+
+       INIT_WORK(&call->work, SRXAFSCB_ProbeUuid);
+       schedule_work(&call->work);
+       return 0;
+}
+
 /*
  * allow the fileserver to ask about the cache manager's capabilities
  */
-static void SRXAFSCB_GetCapabilities(struct work_struct *work)
+static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work)
 {
        struct afs_interface *ifs;
        struct afs_call *call = container_of(work, struct afs_call, work);
@@ -456,10 +563,10 @@ static void SRXAFSCB_GetCapabilities(struct work_struct *work)
 }
 
 /*
- * deliver request data to a CB.GetCapabilities call
+ * deliver request data to a CB.TellMeAboutYourself call
  */
-static int afs_deliver_cb_get_capabilities(struct afs_call *call,
-                                          struct sk_buff *skb, bool last)
+static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call,
+                                                struct sk_buff *skb, bool last)
 {
        _enter(",{%u},%d", skb->len, last);
 
@@ -471,7 +578,7 @@ static int afs_deliver_cb_get_capabilities(struct afs_call *call,
        /* no unmarshalling required */
        call->state = AFS_CALL_REPLYING;
 
-       INIT_WORK(&call->work, SRXAFSCB_GetCapabilities);
+       INIT_WORK(&call->work, SRXAFSCB_TellMeAboutYourself);
        schedule_work(&call->work);
        return 0;
 }
index b58af8f18bc4d36a849e7f314b9c809834a96bae..dfda03d4397d03862ae9b64d0832d4d9463010c5 100644 (file)
@@ -140,7 +140,7 @@ static inline void afs_dir_check_page(struct inode *dir, struct page *page)
 
        if (page->index == 0 && qty != ntohs(dbuf->blocks[0].pagehdr.npages)) {
                printk("kAFS: %s(%lu): wrong number of dir blocks %d!=%hu\n",
-                      __FUNCTION__, dir->i_ino, qty,
+                      __func__, dir->i_ino, qty,
                       ntohs(dbuf->blocks[0].pagehdr.npages));
                goto error;
        }
@@ -159,7 +159,7 @@ static inline void afs_dir_check_page(struct inode *dir, struct page *page)
        for (tmp = 0; tmp < qty; tmp++) {
                if (dbuf->blocks[tmp].pagehdr.magic != AFS_DIR_MAGIC) {
                        printk("kAFS: %s(%lu): bad magic %d/%d is %04hx\n",
-                              __FUNCTION__, dir->i_ino, tmp, qty,
+                              __func__, dir->i_ino, tmp, qty,
                               ntohs(dbuf->blocks[tmp].pagehdr.magic));
                        goto error;
                }
index eec41c76de72135d831f4bf7a00819b503110999..7102824ba8479c6e2d006816fb3555311d56df61 100644 (file)
@@ -757,8 +757,8 @@ void _dbprintk(const char *fmt, ...)
 {
 }
 
-#define kenter(FMT,...)        dbgprintk("==> %s("FMT")",__FUNCTION__ ,##__VA_ARGS__)
-#define kleave(FMT,...)        dbgprintk("<== %s()"FMT"",__FUNCTION__ ,##__VA_ARGS__)
+#define kenter(FMT,...)        dbgprintk("==> %s("FMT")",__func__ ,##__VA_ARGS__)
+#define kleave(FMT,...)        dbgprintk("<== %s()"FMT"",__func__ ,##__VA_ARGS__)
 #define kdebug(FMT,...)        dbgprintk("    "FMT ,##__VA_ARGS__)
 
 
@@ -791,8 +791,8 @@ do {                                                        \
 } while (0)
 
 #else
-#define _enter(FMT,...)        _dbprintk("==> %s("FMT")",__FUNCTION__ ,##__VA_ARGS__)
-#define _leave(FMT,...)        _dbprintk("<== %s()"FMT"",__FUNCTION__ ,##__VA_ARGS__)
+#define _enter(FMT,...)        _dbprintk("==> %s("FMT")",__func__ ,##__VA_ARGS__)
+#define _leave(FMT,...)        _dbprintk("<== %s()"FMT"",__func__ ,##__VA_ARGS__)
 #define _debug(FMT,...)        _dbprintk("    "FMT ,##__VA_ARGS__)
 #endif
 
index 846c7615ac9e516bdb7810bc6498b9b516defbe6..9f7d1ae70269ac9de86404e5b6eb36b6a4d34f29 100644 (file)
@@ -41,6 +41,7 @@ static const struct file_operations afs_proc_cells_fops = {
        .write          = afs_proc_cells_write,
        .llseek         = seq_lseek,
        .release        = seq_release,
+       .owner          = THIS_MODULE,
 };
 
 static int afs_proc_rootcell_open(struct inode *inode, struct file *file);
@@ -56,7 +57,8 @@ static const struct file_operations afs_proc_rootcell_fops = {
        .read           = afs_proc_rootcell_read,
        .write          = afs_proc_rootcell_write,
        .llseek         = no_llseek,
-       .release        = afs_proc_rootcell_release
+       .release        = afs_proc_rootcell_release,
+       .owner          = THIS_MODULE,
 };
 
 static int afs_proc_cell_volumes_open(struct inode *inode, struct file *file);
@@ -80,6 +82,7 @@ static const struct file_operations afs_proc_cell_volumes_fops = {
        .read           = seq_read,
        .llseek         = seq_lseek,
        .release        = afs_proc_cell_volumes_release,
+       .owner          = THIS_MODULE,
 };
 
 static int afs_proc_cell_vlservers_open(struct inode *inode,
@@ -104,6 +107,7 @@ static const struct file_operations afs_proc_cell_vlservers_fops = {
        .read           = seq_read,
        .llseek         = seq_lseek,
        .release        = afs_proc_cell_vlservers_release,
+       .owner          = THIS_MODULE,
 };
 
 static int afs_proc_cell_servers_open(struct inode *inode, struct file *file);
@@ -127,6 +131,7 @@ static const struct file_operations afs_proc_cell_servers_fops = {
        .read           = seq_read,
        .llseek         = seq_lseek,
        .release        = afs_proc_cell_servers_release,
+       .owner          = THIS_MODULE,
 };
 
 /*
@@ -143,17 +148,13 @@ int afs_proc_init(void)
                goto error_dir;
        proc_afs->owner = THIS_MODULE;
 
-       p = create_proc_entry("cells", 0, proc_afs);
+       p = proc_create("cells", 0, proc_afs, &afs_proc_cells_fops);
        if (!p)
                goto error_cells;
-       p->proc_fops = &afs_proc_cells_fops;
-       p->owner = THIS_MODULE;
 
-       p = create_proc_entry("rootcell", 0, proc_afs);
+       p = proc_create("rootcell", 0, proc_afs, &afs_proc_rootcell_fops);
        if (!p)
                goto error_rootcell;
-       p->proc_fops = &afs_proc_rootcell_fops;
-       p->owner = THIS_MODULE;
 
        _leave(" = 0");
        return 0;
@@ -395,26 +396,20 @@ int afs_proc_cell_setup(struct afs_cell *cell)
        if (!cell->proc_dir)
                goto error_dir;
 
-       p = create_proc_entry("servers", 0, cell->proc_dir);
+       p = proc_create_data("servers", 0, cell->proc_dir,
+                            &afs_proc_cell_servers_fops, cell);
        if (!p)
                goto error_servers;
-       p->proc_fops = &afs_proc_cell_servers_fops;
-       p->owner = THIS_MODULE;
-       p->data = cell;
 
-       p = create_proc_entry("vlservers", 0, cell->proc_dir);
+       p = proc_create_data("vlservers", 0, cell->proc_dir,
+                            &afs_proc_cell_vlservers_fops, cell);
        if (!p)
                goto error_vlservers;
-       p->proc_fops = &afs_proc_cell_vlservers_fops;
-       p->owner = THIS_MODULE;
-       p->data = cell;
 
-       p = create_proc_entry("volumes", 0, cell->proc_dir);
+       p = proc_create_data("volumes", 0, cell->proc_dir,
+                            &afs_proc_cell_volumes_fops, cell);
        if (!p)
                goto error_volumes;
-       p->proc_fops = &afs_proc_cell_volumes_fops;
-       p->owner = THIS_MODULE;
-       p->data = cell;
 
        _leave(" = 0");
        return 0;
index ae94e1dea26684b7ec1968ad23ae2a3aca2fc11c..b5253e77eb2f137ee5b1346f848514ad991801e1 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -191,6 +191,43 @@ static int aio_setup_ring(struct kioctx *ctx)
        kunmap_atomic((void *)((unsigned long)__event & PAGE_MASK), km); \
 } while(0)
 
+
+/* __put_ioctx
+ *     Called when the last user of an aio context has gone away,
+ *     and the struct needs to be freed.
+ */
+static void __put_ioctx(struct kioctx *ctx)
+{
+       unsigned nr_events = ctx->max_reqs;
+
+       BUG_ON(ctx->reqs_active);
+
+       cancel_delayed_work(&ctx->wq);
+       cancel_work_sync(&ctx->wq.work);
+       aio_free_ring(ctx);
+       mmdrop(ctx->mm);
+       ctx->mm = NULL;
+       pr_debug("__put_ioctx: freeing %p\n", ctx);
+       kmem_cache_free(kioctx_cachep, ctx);
+
+       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);
+       }
+}
+
+#define get_ioctx(kioctx) do {                                         \
+       BUG_ON(atomic_read(&(kioctx)->users) <= 0);                     \
+       atomic_inc(&(kioctx)->users);                                   \
+} while (0)
+#define put_ioctx(kioctx) do {                                         \
+       BUG_ON(atomic_read(&(kioctx)->users) <= 0);                     \
+       if (unlikely(atomic_dec_and_test(&(kioctx)->users)))            \
+               __put_ioctx(kioctx);                                    \
+} while (0)
+
 /* ioctx_alloc
  *     Allocates and initializes an ioctx.  Returns an ERR_PTR if it failed.
  */
@@ -240,7 +277,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
        if (ctx->max_reqs == 0)
                goto out_cleanup;
 
-       /* now link into global list.  kludge.  FIXME */
+       /* now link into global list. */
        write_lock(&mm->ioctx_list_lock);
        ctx->next = mm->ioctx_list;
        mm->ioctx_list = ctx;
@@ -361,32 +398,6 @@ void exit_aio(struct mm_struct *mm)
        }
 }
 
-/* __put_ioctx
- *     Called when the last user of an aio context has gone away,
- *     and the struct needs to be freed.
- */
-void __put_ioctx(struct kioctx *ctx)
-{
-       unsigned nr_events = ctx->max_reqs;
-
-       BUG_ON(ctx->reqs_active);
-
-       cancel_delayed_work(&ctx->wq);
-       cancel_work_sync(&ctx->wq.work);
-       aio_free_ring(ctx);
-       mmdrop(ctx->mm);
-       ctx->mm = NULL;
-       pr_debug("__put_ioctx: freeing %p\n", ctx);
-       kmem_cache_free(kioctx_cachep, ctx);
-
-       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
  *     Allocate a slot for an aio request.  Increments the users count
  * of the kioctx so that the kioctx stays around until all requests are
@@ -542,10 +553,7 @@ int aio_put_req(struct kiocb *req)
        return ret;
 }
 
-/*     Lookup an ioctx id.  ioctx_list is lockless for reads.
- *     FIXME: this is O(n) and is only suitable for development.
- */
-struct kioctx *lookup_ioctx(unsigned long ctx_id)
+static struct kioctx *lookup_ioctx(unsigned long ctx_id)
 {
        struct kioctx *ioctx;
        struct mm_struct *mm;
@@ -1070,9 +1078,7 @@ static void timeout_func(unsigned long data)
 
 static inline void init_timeout(struct aio_timeout *to)
 {
-       init_timer(&to->timer);
-       to->timer.data = (unsigned long)to;
-       to->timer.function = timeout_func;
+       setup_timer_on_stack(&to->timer, timeout_func, (unsigned long) to);
        to->timed_out = 0;
        to->p = current;
 }
@@ -1205,6 +1211,7 @@ retry:
        if (timeout)
                clear_timeout(&to);
 out:
+       destroy_timer_on_stack(&to.timer);
        return i ? i : ret;
 }
 
@@ -1552,7 +1559,7 @@ static int aio_wake_function(wait_queue_t *wait, unsigned mode,
        return 1;
 }
 
-int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
+static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                         struct iocb *iocb)
 {
        struct kiocb *req;
@@ -1593,7 +1600,7 @@ int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                 * event using the eventfd_signal() function.
                 */
                req->ki_eventfd = eventfd_fget((int) iocb->aio_resfd);
-               if (unlikely(IS_ERR(req->ki_eventfd))) {
+               if (IS_ERR(req->ki_eventfd)) {
                        ret = PTR_ERR(req->ki_eventfd);
                        goto out_put_req;
                }
index 2d4ae40718d9ecdc35119a82a10d264ce5c178ea..c3d352d7fa9304cb44c6ec4e4542bbc46f8ec2b2 100644 (file)
@@ -35,7 +35,7 @@
 /* #define DEBUG */
 
 #ifdef DEBUG
-#define DPRINTK(fmt,args...) do { printk(KERN_DEBUG "pid %d: %s: " fmt "\n" , current->pid , __FUNCTION__ , ##args); } while(0)
+#define DPRINTK(fmt,args...) do { printk(KERN_DEBUG "pid %d: %s: " fmt "\n" , current->pid , __func__ , ##args); } while(0)
 #else
 #define DPRINTK(fmt,args...) do {} while(0)
 #endif
index a54a946a50ae55bc44f04142565834527f07d524..aa4c5ff8a40dfcf65babdd56c9e6fac056b4423f 100644 (file)
@@ -533,9 +533,9 @@ static struct dentry *autofs4_lookup_unhashed(struct autofs_sb_info *sbi, struct
                        goto next;
 
                if (d_unhashed(dentry)) {
-                       struct autofs_info *ino = autofs4_dentry_ino(dentry);
                        struct inode *inode = dentry->d_inode;
 
+                       ino = autofs4_dentry_ino(dentry);
                        list_del_init(&ino->rehash);
                        dget(dentry);
                        /*
index 82123ff3e1dd744db3d766769fafd53d2e133a32..e8717de3bab34f16f551004048fd91a4c6029cb1 100644 (file)
@@ -489,9 +489,9 @@ static void befs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
 {
        befs_inode_info *befs_ino = BEFS_I(dentry->d_inode);
        if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {
-               char *p = nd_get_link(nd);
-               if (!IS_ERR(p))
-                       kfree(p);
+               char *link = nd_get_link(nd);
+               if (!IS_ERR(link))
+                       kfree(link);
        }
 }
 
index 71faf4d2390824ac2f0e001c32bb24c126f7f653..70f5d3a8eede460af9faf2f6e45407cc01f7d086 100644 (file)
@@ -42,7 +42,7 @@ static inline struct bfs_inode_info *BFS_I(struct inode *inode)
 
 
 #define printf(format, args...) \
-       printk(KERN_ERR "BFS-fs: %s(): " format, __FUNCTION__, ## args)
+       printk(KERN_ERR "BFS-fs: %s(): " format, __func__, ## args)
 
 /* inode.c */
 extern struct inode *bfs_iget(struct super_block *sb, unsigned long ino);
index a1bb2244cac772dd31dd8caff79b99fcead5ac3d..ba4cddb92f1ddf02330760e7b7614d7b261a5a64 100644 (file)
@@ -372,21 +372,17 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                         
                flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data);
        } else {
-               static unsigned long error_time, error_time2;
                if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
-                   (N_MAGIC(ex) != NMAGIC) && (jiffies-error_time2) > 5*HZ)
+                   (N_MAGIC(ex) != NMAGIC) && printk_ratelimit())
                {
                        printk(KERN_NOTICE "executable not page aligned\n");
-                       error_time2 = jiffies;
                }
 
-               if ((fd_offset & ~PAGE_MASK) != 0 &&
-                   (jiffies-error_time) > 5*HZ)
+               if ((fd_offset & ~PAGE_MASK) != 0 && printk_ratelimit())
                {
                        printk(KERN_WARNING 
                               "fd_offset is not page aligned. Please convert program: %s\n",
                               bprm->file->f_path.dentry->d_name.name);
-                       error_time = jiffies;
                }
 
                if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
@@ -495,15 +491,13 @@ static int load_aout_library(struct file *file)
        start_addr =  ex.a_entry & 0xfffff000;
 
        if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
-               static unsigned long error_time;
                loff_t pos = N_TXTOFF(ex);
 
-               if ((jiffies-error_time) > 5*HZ)
+               if (printk_ratelimit())
                {
                        printk(KERN_WARNING 
                               "N_TXTOFF is not page aligned. Please convert library: %s\n",
                               file->f_path.dentry->d_name.name);
-                       error_time = jiffies;
                }
                down_write(&current->mm->mmap_sem);
                do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
index 9924581df6f6ccbc35520237cbdf8c9c079559f8..b25707fee2ccad4598146224a5b5c5abcf3c2f99 100644 (file)
@@ -1255,26 +1255,23 @@ static int writenote(struct memelfnote *men, struct file *file,
 static void fill_elf_header(struct elfhdr *elf, int segs,
                            u16 machine, u32 flags, u8 osabi)
 {
+       memset(elf, 0, sizeof(*elf));
+
        memcpy(elf->e_ident, ELFMAG, SELFMAG);
        elf->e_ident[EI_CLASS] = ELF_CLASS;
        elf->e_ident[EI_DATA] = ELF_DATA;
        elf->e_ident[EI_VERSION] = EV_CURRENT;
        elf->e_ident[EI_OSABI] = ELF_OSABI;
-       memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
 
        elf->e_type = ET_CORE;
        elf->e_machine = machine;
        elf->e_version = EV_CURRENT;
-       elf->e_entry = 0;
        elf->e_phoff = sizeof(struct elfhdr);
-       elf->e_shoff = 0;
        elf->e_flags = flags;
        elf->e_ehsize = sizeof(struct elfhdr);
        elf->e_phentsize = sizeof(struct elf_phdr);
        elf->e_phnum = segs;
-       elf->e_shentsize = 0;
-       elf->e_shnum = 0;
-       elf->e_shstrndx = 0;
+
        return;
 }
 
@@ -1725,26 +1722,25 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
 
        info->thread_status_size = 0;
        if (signr) {
-               struct elf_thread_status *tmp;
+               struct elf_thread_status *ets;
                rcu_read_lock();
                do_each_thread(g, p)
                        if (current->mm == p->mm && current != p) {
-                               tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC);
-                               if (!tmp) {
+                               ets = kzalloc(sizeof(*ets), GFP_ATOMIC);
+                               if (!ets) {
                                        rcu_read_unlock();
                                        return 0;
                                }
-                               tmp->thread = p;
-                               list_add(&tmp->list, &info->thread_list);
+                               ets->thread = p;
+                               list_add(&ets->list, &info->thread_list);
                        }
                while_each_thread(g, p);
                rcu_read_unlock();
                list_for_each(t, &info->thread_list) {
-                       struct elf_thread_status *tmp;
                        int sz;
 
-                       tmp = list_entry(t, struct elf_thread_status, list);
-                       sz = elf_dump_thread_status(signr, tmp);
+                       ets = list_entry(t, struct elf_thread_status, list);
+                       sz = elf_dump_thread_status(signr, ets);
                        info->thread_status_size += sz;
                }
        }
@@ -2000,10 +1996,10 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un
 
                for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) {
                        struct page *page;
-                       struct vm_area_struct *vma;
+                       struct vm_area_struct *tmp_vma;
 
                        if (get_user_pages(current, current->mm, addr, 1, 0, 1,
-                                               &page, &vma) <= 0) {
+                                               &page, &tmp_vma) <= 0) {
                                DUMP_SEEK(PAGE_SIZE);
                        } else {
                                if (page == ZERO_PAGE(0)) {
@@ -2013,7 +2009,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un
                                        }
                                } else {
                                        void *kaddr;
-                                       flush_cache_page(vma, addr,
+                                       flush_cache_page(tmp_vma, addr,
                                                         page_to_pfn(page));
                                        kaddr = kmap(page);
                                        if ((size += PAGE_SIZE) > limit ||
index 32649f2a16544502c8affe2d147ac89d1e02ae50..ddd35d87339143207f6074a49752dcc40a4b5003 100644 (file)
@@ -136,8 +136,8 @@ static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params,
 
        retval = kernel_read(file, params->hdr.e_phoff,
                             (char *) params->phdrs, size);
-       if (retval < 0)
-               return retval;
+       if (unlikely(retval != size))
+               return retval < 0 ? retval : -ENOEXEC;
 
        /* determine stack size for this binary */
        phdr = params->phdrs;
@@ -218,8 +218,11 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
                                             phdr->p_offset,
                                             interpreter_name,
                                             phdr->p_filesz);
-                       if (retval < 0)
+                       if (unlikely(retval != phdr->p_filesz)) {
+                               if (retval >= 0)
+                                       retval = -ENOEXEC;
                                goto error;
+                       }
 
                        retval = -ENOENT;
                        if (interpreter_name[phdr->p_filesz - 1] != '\0')
@@ -245,8 +248,11 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
 
                        retval = kernel_read(interpreter, 0, bprm->buf,
                                             BINPRM_BUF_SIZE);
-                       if (retval < 0)
+                       if (unlikely(retval != BINPRM_BUF_SIZE)) {
+                               if (retval >= 0)
+                                       retval = -ENOEXEC;
                                goto error;
+                       }
 
                        interp_params.hdr = *((struct elfhdr *) bprm->buf);
                        break;
index f95ae9789c913d81d0df5d17250bced9c5479855..f9c88d0c8cedeabcfdca1a5f81a51e1e293a59ea 100644 (file)
@@ -43,7 +43,7 @@ static int load_em86(struct linux_binprm *bprm,struct pt_regs *regs)
                        return -ENOEXEC;
        }
 
-       bprm->sh_bang++;        /* Well, the bang-shell is implicit... */
+       bprm->sh_bang = 1;      /* Well, the bang-shell is implicit... */
        allow_write_access(bprm->file);
        fput(bprm->file);
        bprm->file = NULL;
index 0498b181dd525cc4855b3284353abec948633e7e..3b40d45a3a16501ca0ea28563b8049c6e3718698 100644 (file)
@@ -531,7 +531,8 @@ static int load_flat_file(struct linux_binprm * bprm,
                DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
 
                down_write(&current->mm->mmap_sem);
-               textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_PRIVATE, 0);
+               textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC,
+                                 MAP_PRIVATE|MAP_EXECUTABLE, 0);
                up_write(&current->mm->mmap_sem);
                if (!textpos  || textpos >= (unsigned long) -4096) {
                        if (!textpos)
@@ -932,14 +933,8 @@ static int __init init_flat_binfmt(void)
        return register_binfmt(&flat_format);
 }
 
-static void __exit exit_flat_binfmt(void)
-{
-       unregister_binfmt(&flat_format);
-}
-
 /****************************************************************************/
 
 core_initcall(init_flat_binfmt);
-module_exit(exit_flat_binfmt);
 
 /****************************************************************************/
index dbf0ac0523de14d49edcc58b43ab7c62a407e406..7191306367c5d11912ceed01c5fce4925b528eba 100644 (file)
@@ -115,6 +115,12 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
        if (!enabled)
                goto _ret;
 
+       retval = -ENOEXEC;
+       if (bprm->misc_bang)
+               goto _ret;
+
+       bprm->misc_bang = 1;
+
        /* to keep locking time low, we copy the interpreter string */
        read_lock(&entries_lock);
        fmt = check_file(bprm);
index ab33939b12a7efb8d754fcc80b89bfc88651a33b..9e3963f7ebf19f85a1742ff034bbb518d51a6aff 100644 (file)
@@ -29,7 +29,7 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs)
         * Sorta complicated, but hopefully it will work.  -TYT
         */
 
-       bprm->sh_bang++;
+       bprm->sh_bang = 1;
        allow_write_access(bprm->file);
        fput(bprm->file);
        bprm->file = NULL;
index 6e0b6f66df0315a450f467c1025c8b1042845ced..799f86deff243213256103ee76ff7560098fe965 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -937,6 +937,95 @@ struct bio *bio_map_kern(struct request_queue *q, void *data, unsigned int len,
        return ERR_PTR(-EINVAL);
 }
 
+static void bio_copy_kern_endio(struct bio *bio, int err)
+{
+       struct bio_vec *bvec;
+       const int read = bio_data_dir(bio) == READ;
+       char *p = bio->bi_private;
+       int i;
+
+       __bio_for_each_segment(bvec, bio, i, 0) {
+               char *addr = page_address(bvec->bv_page);
+
+               if (read && !err)
+                       memcpy(p, addr, bvec->bv_len);
+
+               __free_page(bvec->bv_page);
+               p += bvec->bv_len;
+       }
+
+       bio_put(bio);
+}
+
+/**
+ *     bio_copy_kern   -       copy kernel address into bio
+ *     @q: the struct request_queue for the bio
+ *     @data: pointer to buffer to copy
+ *     @len: length in bytes
+ *     @gfp_mask: allocation flags for bio and page allocation
+ *
+ *     copy the kernel address into a bio suitable for io to a block
+ *     device. Returns an error pointer in case of error.
+ */
+struct bio *bio_copy_kern(struct request_queue *q, void *data, unsigned int len,
+                         gfp_t gfp_mask, int reading)
+{
+       unsigned long kaddr = (unsigned long)data;
+       unsigned long end = (kaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       unsigned long start = kaddr >> PAGE_SHIFT;
+       const int nr_pages = end - start;
+       struct bio *bio;
+       struct bio_vec *bvec;
+       int i, ret;
+
+       bio = bio_alloc(gfp_mask, nr_pages);
+       if (!bio)
+               return ERR_PTR(-ENOMEM);
+
+       while (len) {
+               struct page *page;
+               unsigned int bytes = PAGE_SIZE;
+
+               if (bytes > len)
+                       bytes = len;
+
+               page = alloc_page(q->bounce_gfp | gfp_mask);
+               if (!page) {
+                       ret = -ENOMEM;
+                       goto cleanup;
+               }
+
+               if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes) {
+                       ret = -EINVAL;
+                       goto cleanup;
+               }
+
+               len -= bytes;
+       }
+
+       if (!reading) {
+               void *p = data;
+
+               bio_for_each_segment(bvec, bio, i) {
+                       char *addr = page_address(bvec->bv_page);
+
+                       memcpy(addr, p, bvec->bv_len);
+                       p += bvec->bv_len;
+               }
+       }
+
+       bio->bi_private = data;
+       bio->bi_end_io = bio_copy_kern_endio;
+       return bio;
+cleanup:
+       bio_for_each_segment(bvec, bio, i)
+               __free_page(bvec->bv_page);
+
+       bio_put(bio);
+
+       return ERR_PTR(ret);
+}
+
 /*
  * bio_set_pages_dirty() and bio_check_pages_dirty() are support functions
  * for performing direct-IO in BIOs.
@@ -1273,6 +1362,7 @@ EXPORT_SYMBOL(bio_get_nr_vecs);
 EXPORT_SYMBOL(bio_map_user);
 EXPORT_SYMBOL(bio_unmap_user);
 EXPORT_SYMBOL(bio_map_kern);
+EXPORT_SYMBOL(bio_copy_kern);
 EXPORT_SYMBOL(bio_pair_release);
 EXPORT_SYMBOL(bio_split);
 EXPORT_SYMBOL(bio_split_pool);
index 3db4a26adc44294f0a15a77aba595cc4336b31fd..a073f3f4f013c5c349afede7edb715672bfd4928 100644 (file)
@@ -1101,7 +1101,7 @@ grow_buffers(struct block_device *bdev, sector_t block, int size)
 
                printk(KERN_ERR "%s: requested out-of-range block %llu for "
                        "device %s\n",
-                       __FUNCTION__, (unsigned long long)block,
+                       __func__, (unsigned long long)block,
                        bdevname(bdev, b));
                return -EIO;
        }
@@ -2211,8 +2211,8 @@ out:
        return err;
 }
 
-int cont_expand_zero(struct file *file, struct address_space *mapping,
-                       loff_t pos, loff_t *bytes)
+static int cont_expand_zero(struct file *file, struct address_space *mapping,
+                           loff_t pos, loff_t *bytes)
 {
        struct inode *inode = mapping->host;
        unsigned blocksize = 1 << inode->i_blkbits;
@@ -2328,23 +2328,6 @@ int block_commit_write(struct page *page, unsigned from, unsigned to)
        return 0;
 }
 
-int generic_commit_write(struct file *file, struct page *page,
-               unsigned from, unsigned to)
-{
-       struct inode *inode = page->mapping->host;
-       loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
-       __block_commit_write(inode,page,from,to);
-       /*
-        * No need to use i_size_read() here, the i_size
-        * cannot change under us because we hold i_mutex.
-        */
-       if (pos > inode->i_size) {
-               i_size_write(inode, pos);
-               mark_inode_dirty(inode);
-       }
-       return 0;
-}
-
 /*
  * block_page_mkwrite() is not allowed to change the file size as it gets
  * called from a page fault handler when a page is first dirtied. Hence we must
@@ -3315,7 +3298,6 @@ EXPORT_SYMBOL(end_buffer_write_sync);
 EXPORT_SYMBOL(file_fsync);
 EXPORT_SYMBOL(fsync_bdev);
 EXPORT_SYMBOL(generic_block_bmap);
-EXPORT_SYMBOL(generic_commit_write);
 EXPORT_SYMBOL(generic_cont_expand_simple);
 EXPORT_SYMBOL(init_buffer);
 EXPORT_SYMBOL(invalidate_bdev);
index 038674aa88a72c09a88388ee7cf1b54839675052..68e510b88457e85d8831aa0b48a0479c137d3cb3 100644 (file)
@@ -55,7 +55,6 @@ static struct char_device_struct {
        unsigned int baseminor;
        int minorct;
        char name[64];
-       struct file_operations *fops;
        struct cdev *cdev;              /* will die */
 } *chrdevs[CHRDEV_MAJOR_HASH_SIZE];
 
index 0228ed06069e95c88b3b4a032b5b423f474ca190..cc950f69e51ea5b2e5a13135258151e4560c9b2f 100644 (file)
@@ -468,7 +468,7 @@ cifs_proc_init(void)
 {
        struct proc_dir_entry *pde;
 
-       proc_fs_cifs = proc_mkdir("cifs", proc_root_fs);
+       proc_fs_cifs = proc_mkdir("fs/cifs", NULL);
        if (proc_fs_cifs == NULL)
                return;
 
@@ -559,7 +559,7 @@ cifs_proc_clean(void)
        remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
        remove_proc_entry("Experimental", proc_fs_cifs);
        remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
-       remove_proc_entry("cifs", proc_root_fs);
+       remove_proc_entry("fs/cifs", NULL);
 }
 
 static int
index 95a54253c0479989ec20f047d4bd821ecd5adf30..e1c854890f9400b9467419ce9e625084391d9853 100644 (file)
@@ -134,7 +134,7 @@ void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr)
         unsigned int valid;
 
         /* clean out */        
-        vattr->va_mode = (umode_t) -1;
+       vattr->va_mode = -1;
         vattr->va_uid = (vuid_t) -1; 
         vattr->va_gid = (vgid_t) -1;
         vattr->va_size = (off_t) -1;
index f89ff083079ba5b8fd1595f233c3c9b949d472de..3d2580e00a3e272e0cfe04103c98466e2daa15e7 100644 (file)
@@ -345,7 +345,7 @@ static int coda_symlink(struct inode *dir_inode, struct dentry *de,
 }
 
 /* destruction routines: unlink, rmdir */
-int coda_unlink(struct inode *dir, struct dentry *de)
+static int coda_unlink(struct inode *dir, struct dentry *de)
 {
         int error;
        const char *name = de->d_name.name;
@@ -365,7 +365,7 @@ int coda_unlink(struct inode *dir, struct dentry *de)
        return 0;
 }
 
-int coda_rmdir(struct inode *dir, struct dentry *de)
+static int coda_rmdir(struct inode *dir, struct dentry *de)
 {
        const char *name = de->d_name.name;
        int len = de->d_name.len;
@@ -424,7 +424,7 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
 
 
 /* file operations for directories */
-int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir)
+static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir)
 {
        struct coda_file_info *cfi;
        struct file *host_file;
index 2ce4456aad309eebc3df3c200178561046d87093..139dc93c092d697b10d540a12020bd92e2e84b41 100644 (file)
@@ -1634,7 +1634,7 @@ sticky:
        return ret;
 }
 
-#ifdef TIF_RESTORE_SIGMASK
+#ifdef HAVE_SET_RESTORE_SIGMASK
 asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
        compat_ulong_t __user *outp, compat_ulong_t __user *exp,
        struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask,
@@ -1720,7 +1720,7 @@ sticky:
                if (sigmask) {
                        memcpy(&current->saved_sigmask, &sigsaved,
                                        sizeof(sigsaved));
-                       set_thread_flag(TIF_RESTORE_SIGMASK);
+                       set_restore_sigmask();
                }
        } else if (sigmask)
                sigprocmask(SIG_SETMASK, &sigsaved, NULL);
@@ -1791,7 +1791,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
                if (sigmask) {
                        memcpy(&current->saved_sigmask, &sigsaved,
                                sizeof(sigsaved));
-                       set_thread_flag(TIF_RESTORE_SIGMASK);
+                       set_restore_sigmask();
                }
                ret = -ERESTARTNOHAND;
        } else if (sigmask)
@@ -1825,7 +1825,7 @@ sticky:
 
        return ret;
 }
-#endif /* TIF_RESTORE_SIGMASK */
+#endif /* HAVE_SET_RESTORE_SIGMASK */
 
 #if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
 /* Stuff for NFS server syscalls... */
@@ -2080,7 +2080,7 @@ long asmlinkage compat_sys_nfsservctl(int cmd, void *notused, void *notused2)
 
 #ifdef CONFIG_EPOLL
 
-#ifdef TIF_RESTORE_SIGMASK
+#ifdef HAVE_SET_RESTORE_SIGMASK
 asmlinkage long compat_sys_epoll_pwait(int epfd,
                        struct compat_epoll_event __user *events,
                        int maxevents, int timeout,
@@ -2117,14 +2117,14 @@ asmlinkage long compat_sys_epoll_pwait(int epfd,
                if (err == -EINTR) {
                        memcpy(&current->saved_sigmask, &sigsaved,
                               sizeof(sigsaved));
-                       set_thread_flag(TIF_RESTORE_SIGMASK);
+                       set_restore_sigmask();
                } else
                        sigprocmask(SIG_SETMASK, &sigsaved, NULL);
        }
 
        return err;
 }
-#endif /* TIF_RESTORE_SIGMASK */
+#endif /* HAVE_SET_RESTORE_SIGMASK */
 
 #endif /* CONFIG_EPOLL */
 
index c6e72aebd16b43e7b16339cb69869472fccbdd24..97dba0d92348d27692c4f9c10bc6e99c25333cd8 100644 (file)
@@ -1046,14 +1046,14 @@ static int vt_check(struct file *file)
        struct inode *inode = file->f_path.dentry->d_inode;
        struct vc_data *vc;
        
-       if (file->f_op->ioctl != tty_ioctl)
+       if (file->f_op->unlocked_ioctl != tty_ioctl)
                return -EINVAL;
                        
        tty = (struct tty_struct *)file->private_data;
        if (tty_paranoia_check(tty, inode, "tty_ioctl"))
                return -EINVAL;
                                                        
-       if (tty->driver->ioctl != vt_ioctl)
+       if (tty->ops->ioctl != vt_ioctl)
                return -EINVAL;
 
        vc = (struct vc_data *)tty->driver_data;
index 397cb503a180da62a9cbcdc2f0aeb86b81851cc6..2b6cb23dd14e99a4165af595a1f6670e002d8d3b 100644 (file)
@@ -115,7 +115,7 @@ configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *pp
                        goto out;
        }
        pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
-                __FUNCTION__, count, *ppos, buffer->page);
+                __func__, count, *ppos, buffer->page);
        retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
                                         buffer->count);
 out:
index 4c1ebff778eef936479b2869ed34c620694479fb..b9a1d810346d3883c8a908079ae1f4e8be6fe217 100644 (file)
@@ -47,7 +47,7 @@ static const struct address_space_operations configfs_aops = {
 
 static struct backing_dev_info configfs_backing_dev_info = {
        .ra_pages       = 0,    /* No readahead */
-       .capabilities   = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
+       .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK,
 };
 
 static const struct inode_operations configfs_inode_operations ={
index de3b31d0a37d88a44185cb6be1efeefed6bc1cab..8421cea7d8c7b1460b0cfdf90e831a3012ddf803 100644 (file)
@@ -92,7 +92,7 @@ static int configfs_fill_super(struct super_block *sb, void *data, int silent)
 
        root = d_alloc_root(inode);
        if (!root) {
-               pr_debug("%s: could not get root dentry!\n",__FUNCTION__);
+               pr_debug("%s: could not get root dentry!\n",__func__);
                iput(inode);
                return -ENOMEM;
        }
index 78929ea84ff2da08688619b2b83d74700ca0dc25..2a731ef5f305c3bdd803937a3d893997a2ca6361 100644 (file)
@@ -210,13 +210,13 @@ static int configfs_get_target_path(struct config_item * item, struct config_ite
        if (size > PATH_MAX)
                return -ENAMETOOLONG;
 
-       pr_debug("%s: depth = %d, size = %d\n", __FUNCTION__, depth, size);
+       pr_debug("%s: depth = %d, size = %d\n", __func__, depth, size);
 
        for (s = path; depth--; s += 3)
                strcpy(s,"../");
 
        fill_item_path(target, path, size);
-       pr_debug("%s: path = '%s'\n", __FUNCTION__, path);
+       pr_debug("%s: path = '%s'\n", __func__, path);
 
        return 0;
 }
index f120e1207874715b052788ea9105458da9348145..285b64a8b06e125b1aee42a8317cfd0873d69f20 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/tty.h>
+#include <linux/mutex.h>
+#include <linux/idr.h>
 #include <linux/devpts_fs.h>
 #include <linux/parser.h>
 #include <linux/fsnotify.h>
 
 #define DEVPTS_DEFAULT_MODE 0600
 
+extern int pty_limit;                  /* Config limit on Unix98 ptys */
+static DEFINE_IDR(allocated_ptys);
+static DEFINE_MUTEX(allocated_ptys_lock);
+
 static struct vfsmount *devpts_mnt;
 static struct dentry *devpts_root;
 
@@ -171,9 +177,44 @@ static struct dentry *get_node(int num)
        return lookup_one_len(s, root, sprintf(s, "%d", num));
 }
 
+int devpts_new_index(void)
+{
+       int index;
+       int idr_ret;
+
+retry:
+       if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) {
+               return -ENOMEM;
+       }
+
+       mutex_lock(&allocated_ptys_lock);
+       idr_ret = idr_get_new(&allocated_ptys, NULL, &index);
+       if (idr_ret < 0) {
+               mutex_unlock(&allocated_ptys_lock);
+               if (idr_ret == -EAGAIN)
+                       goto retry;
+               return -EIO;
+       }
+
+       if (index >= pty_limit) {
+               idr_remove(&allocated_ptys, index);
+               mutex_unlock(&allocated_ptys_lock);
+               return -EIO;
+       }
+       mutex_unlock(&allocated_ptys_lock);
+       return index;
+}
+
+void devpts_kill_index(int idx)
+{
+       mutex_lock(&allocated_ptys_lock);
+       idr_remove(&allocated_ptys, idx);
+       mutex_unlock(&allocated_ptys_lock);
+}
+
 int devpts_pty_new(struct tty_struct *tty)
 {
-       int number = tty->index;
+       int number = tty->index; /* tty layer puts index from devpts_new_index() in here */
        struct tty_driver *driver = tty->driver;
        dev_t device = MKDEV(driver->major, driver->minor_start+number);
        struct dentry *dentry;
index b64e55e0515d058d6884e9408b9e7fb0580e443d..499e16759e96fea13329dc05d5408194fa96e4e9 100644 (file)
@@ -200,7 +200,7 @@ int __init dlm_lockspace_init(void)
 
        dlm_kset = kset_create_and_add("dlm", NULL, kernel_kobj);
        if (!dlm_kset) {
-               printk(KERN_WARNING "%s: can not create kset\n", __FUNCTION__);
+               printk(KERN_WARNING "%s: can not create kset\n", __func__);
                return -ENOMEM;
        }
        return 0;
index 59375efcf39d6769d94a6d77ef33a06054e4f4b9..3e5637fc377962e1aaca5665f3e03d89366673e3 100644 (file)
@@ -14,18 +14,26 @@ int sysctl_drop_caches;
 
 static void drop_pagecache_sb(struct super_block *sb)
 {
-       struct inode *inode;
+       struct inode *inode, *toput_inode = NULL;
 
        spin_lock(&inode_lock);
        list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
                if (inode->i_state & (I_FREEING|I_WILL_FREE))
                        continue;
+               if (inode->i_mapping->nrpages == 0)
+                       continue;
+               __iget(inode);
+               spin_unlock(&inode_lock);
                __invalidate_mapping_pages(inode->i_mapping, 0, -1, true);
+               iput(toput_inode);
+               toput_inode = inode;
+               spin_lock(&inode_lock);
        }
        spin_unlock(&inode_lock);
+       iput(toput_inode);
 }
 
-void drop_pagecache(void)
+static void drop_pagecache(void)
 {
        struct super_block *sb;
 
@@ -45,7 +53,7 @@ restart:
        spin_unlock(&sb_lock);
 }
 
-void drop_slab(void)
+static void drop_slab(void)
 {
        int nr_objects;
 
index 768857015516f54e9109fab114929cb25389cd32..1e34a7fd4884391b5bec9a3de93bc4dfb86d7d2b 100644 (file)
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o
 
-ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o netlink.o debug.o
+ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o netlink.o miscdev.o debug.o
index a066e109ad9c05a7cbc0670f92045a3475e9aac1..cd62d75b2cc030d27b275423eaba578b3c93eceb 100644 (file)
@@ -119,21 +119,21 @@ static int ecryptfs_calculate_md5(char *dst,
        if (rc) {
                printk(KERN_ERR
                       "%s: Error initializing crypto hash; rc = [%d]\n",
-                      __FUNCTION__, rc);
+                      __func__, rc);
                goto out;
        }
        rc = crypto_hash_update(&desc, &sg, len);
        if (rc) {
                printk(KERN_ERR
                       "%s: Error updating crypto hash; rc = [%d]\n",
-                      __FUNCTION__, rc);
+                      __func__, rc);
                goto out;
        }
        rc = crypto_hash_final(&desc, dst);
        if (rc) {
                printk(KERN_ERR
                       "%s: Error finalizing crypto hash; rc = [%d]\n",
-                      __FUNCTION__, rc);
+                      __func__, rc);
                goto out;
        }
 out:
@@ -437,7 +437,7 @@ static int ecryptfs_encrypt_extent(struct page *enc_extent_page,
        if (rc < 0) {
                printk(KERN_ERR "%s: Error attempting to encrypt page with "
                       "page->index = [%ld], extent_offset = [%ld]; "
-                      "rc = [%d]\n", __FUNCTION__, page->index, extent_offset,
+                      "rc = [%d]\n", __func__, page->index, extent_offset,
                       rc);
                goto out;
        }
@@ -487,7 +487,7 @@ int ecryptfs_encrypt_page(struct page *page)
                                                       0, PAGE_CACHE_SIZE);
                if (rc)
                        printk(KERN_ERR "%s: Error attempting to copy "
-                              "page at index [%ld]\n", __FUNCTION__,
+                              "page at index [%ld]\n", __func__,
                               page->index);
                goto out;
        }
@@ -508,7 +508,7 @@ int ecryptfs_encrypt_page(struct page *page)
                                             extent_offset);
                if (rc) {
                        printk(KERN_ERR "%s: Error encrypting extent; "
-                              "rc = [%d]\n", __FUNCTION__, rc);
+                              "rc = [%d]\n", __func__, rc);
                        goto out;
                }
                ecryptfs_lower_offset_for_extent(
@@ -569,7 +569,7 @@ static int ecryptfs_decrypt_extent(struct page *page,
        if (rc < 0) {
                printk(KERN_ERR "%s: Error attempting to decrypt to page with "
                       "page->index = [%ld], extent_offset = [%ld]; "
-                      "rc = [%d]\n", __FUNCTION__, page->index, extent_offset,
+                      "rc = [%d]\n", __func__, page->index, extent_offset,
                       rc);
                goto out;
        }
@@ -622,7 +622,7 @@ int ecryptfs_decrypt_page(struct page *page)
                                                      ecryptfs_inode);
                if (rc)
                        printk(KERN_ERR "%s: Error attempting to copy "
-                              "page at index [%ld]\n", __FUNCTION__,
+                              "page at index [%ld]\n", __func__,
                               page->index);
                goto out;
        }
@@ -656,7 +656,7 @@ int ecryptfs_decrypt_page(struct page *page)
                                             extent_offset);
                if (rc) {
                        printk(KERN_ERR "%s: Error encrypting extent; "
-                              "rc = [%d]\n", __FUNCTION__, rc);
+                              "rc = [%d]\n", __func__, rc);
                        goto out;
                }
        }
@@ -1215,7 +1215,7 @@ int ecryptfs_read_and_validate_header_region(char *data,
                                 ecryptfs_inode);
        if (rc) {
                printk(KERN_ERR "%s: Error reading header region; rc = [%d]\n",
-                      __FUNCTION__, rc);
+                      __func__, rc);
                goto out;
        }
        if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES)) {
@@ -1246,7 +1246,6 @@ ecryptfs_write_header_metadata(char *virt,
        (*written) = 6;
 }
 
-struct kmem_cache *ecryptfs_header_cache_0;
 struct kmem_cache *ecryptfs_header_cache_1;
 struct kmem_cache *ecryptfs_header_cache_2;
 
@@ -1320,7 +1319,7 @@ ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat,
                                  0, crypt_stat->num_header_bytes_at_front);
        if (rc)
                printk(KERN_ERR "%s: Error attempting to write header "
-                      "information to lower file; rc = [%d]\n", __FUNCTION__,
+                      "information to lower file; rc = [%d]\n", __func__,
                       rc);
        return rc;
 }
@@ -1365,14 +1364,14 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry)
                }
        } else {
                printk(KERN_WARNING "%s: Encrypted flag not set\n",
-                      __FUNCTION__);
+                      __func__);
                rc = -EINVAL;
                goto out;
        }
        /* Released in this function */
        virt = kzalloc(crypt_stat->num_header_bytes_at_front, GFP_KERNEL);
        if (!virt) {
-               printk(KERN_ERR "%s: Out of memory\n", __FUNCTION__);
+               printk(KERN_ERR "%s: Out of memory\n", __func__);
                rc = -ENOMEM;
                goto out;
        }
@@ -1380,7 +1379,7 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry)
                                         ecryptfs_dentry);
        if (unlikely(rc)) {
                printk(KERN_ERR "%s: Error whilst writing headers; rc = [%d]\n",
-                      __FUNCTION__, rc);
+                      __func__, rc);
                goto out_free;
        }
        if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
@@ -1391,7 +1390,7 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry)
                                                         ecryptfs_dentry, virt);
        if (rc) {
                printk(KERN_ERR "%s: Error writing metadata out to lower file; "
-                      "rc = [%d]\n", __FUNCTION__, rc);
+                      "rc = [%d]\n", __func__, rc);
                goto out_free;
        }
 out_free:
@@ -1585,7 +1584,7 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
        if (!page_virt) {
                rc = -ENOMEM;
                printk(KERN_ERR "%s: Unable to allocate page_virt\n",
-                      __FUNCTION__);
+                      __func__);
                goto out;
        }
        rc = ecryptfs_read_lower(page_virt, 0, crypt_stat->extent_size,
index 5007f788da01cec21fb39be75f714840ce6d29e9..951ee33a022df4adfb0427c737208f285a7225ac 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Copyright (C) 1997-2003 Erez Zadok
  * Copyright (C) 2001-2003 Stony Brook University
- * Copyright (C) 2004-2007 International Business Machines Corp.
+ * Copyright (C) 2004-2008 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
  *              Trevor S. Highland <trevor.highland@gmail.com>
  *              Tyler Hicks <tyhicks@ou.edu>
@@ -34,6 +34,7 @@
 #include <linux/namei.h>
 #include <linux/scatterlist.h>
 #include <linux/hash.h>
+#include <linux/nsproxy.h>
 
 /* Version verification for shared data structures w/ userspace */
 #define ECRYPTFS_VERSION_MAJOR 0x00
 #define ECRYPTFS_VERSIONING_POLICY                0x00000008
 #define ECRYPTFS_VERSIONING_XATTR                 0x00000010
 #define ECRYPTFS_VERSIONING_MULTKEY               0x00000020
+#define ECRYPTFS_VERSIONING_DEVMISC               0x00000040
 #define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \
                                  | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \
                                  | ECRYPTFS_VERSIONING_PUBKEY \
                                  | ECRYPTFS_VERSIONING_XATTR \
-                                 | ECRYPTFS_VERSIONING_MULTKEY)
+                                 | ECRYPTFS_VERSIONING_MULTKEY \
+                                 | ECRYPTFS_VERSIONING_DEVMISC)
 #define ECRYPTFS_MAX_PASSWORD_LENGTH 64
 #define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH
 #define ECRYPTFS_SALT_SIZE 8
 #define ECRYPTFS_DEFAULT_MSG_CTX_ELEMS 32
 #define ECRYPTFS_DEFAULT_SEND_TIMEOUT HZ
 #define ECRYPTFS_MAX_MSG_CTX_TTL (HZ*3)
-#define ECRYPTFS_NLMSG_HELO 100
-#define ECRYPTFS_NLMSG_QUIT 101
-#define ECRYPTFS_NLMSG_REQUEST 102
-#define ECRYPTFS_NLMSG_RESPONSE 103
 #define ECRYPTFS_MAX_PKI_NAME_BYTES 16
 #define ECRYPTFS_DEFAULT_NUM_USERS 4
 #define ECRYPTFS_MAX_NUM_USERS 32768
 #define ECRYPTFS_TRANSPORT_NETLINK 0
 #define ECRYPTFS_TRANSPORT_CONNECTOR 1
 #define ECRYPTFS_TRANSPORT_RELAYFS 2
-#define ECRYPTFS_DEFAULT_TRANSPORT ECRYPTFS_TRANSPORT_NETLINK
+#define ECRYPTFS_TRANSPORT_MISCDEV 3
+#define ECRYPTFS_DEFAULT_TRANSPORT ECRYPTFS_TRANSPORT_MISCDEV
 #define ECRYPTFS_XATTR_NAME "user.ecryptfs"
 
 #define RFC2440_CIPHER_DES3_EDE 0x02
@@ -366,32 +366,63 @@ struct ecryptfs_auth_tok_list_item {
 };
 
 struct ecryptfs_message {
+       /* Can never be greater than ecryptfs_message_buf_len */
+       /* Used to find the parent msg_ctx */
+       /* Inherits from msg_ctx->index */
        u32 index;
        u32 data_len;
        u8 data[];
 };
 
 struct ecryptfs_msg_ctx {
-#define ECRYPTFS_MSG_CTX_STATE_FREE      0x0001
-#define ECRYPTFS_MSG_CTX_STATE_PENDING   0x0002
-#define ECRYPTFS_MSG_CTX_STATE_DONE      0x0003
-       u32 state;
-       unsigned int index;
-       unsigned int counter;
+#define ECRYPTFS_MSG_CTX_STATE_FREE     0x01
+#define ECRYPTFS_MSG_CTX_STATE_PENDING  0x02
+#define ECRYPTFS_MSG_CTX_STATE_DONE     0x03
+#define ECRYPTFS_MSG_CTX_STATE_NO_REPLY 0x04
+       u8 state;
+#define ECRYPTFS_MSG_HELO 100
+#define ECRYPTFS_MSG_QUIT 101
+#define ECRYPTFS_MSG_REQUEST 102
+#define ECRYPTFS_MSG_RESPONSE 103
+       u8 type;
+       u32 index;
+       /* Counter converts to a sequence number. Each message sent
+        * out for which we expect a response has an associated
+        * sequence number. The response must have the same sequence
+        * number as the counter for the msg_stc for the message to be
+        * valid. */
+       u32 counter;
+       size_t msg_size;
        struct ecryptfs_message *msg;
        struct task_struct *task;
        struct list_head node;
+       struct list_head daemon_out_list;
        struct mutex mux;
 };
 
 extern unsigned int ecryptfs_transport;
 
-struct ecryptfs_daemon_id {
-       pid_t pid;
-       uid_t uid;
-       struct hlist_node id_chain;
+struct ecryptfs_daemon;
+
+struct ecryptfs_daemon {
+#define ECRYPTFS_DAEMON_IN_READ      0x00000001
+#define ECRYPTFS_DAEMON_IN_POLL      0x00000002
+#define ECRYPTFS_DAEMON_ZOMBIE       0x00000004
+#define ECRYPTFS_DAEMON_MISCDEV_OPEN 0x00000008
+       u32 flags;
+       u32 num_queued_msg_ctx;
+       struct pid *pid;
+       uid_t euid;
+       struct user_namespace *user_ns;
+       struct task_struct *task;
+       struct mutex mux;
+       struct list_head msg_ctx_out_queue;
+       wait_queue_head_t wait;
+       struct hlist_node euid_chain;
 };
 
+extern struct mutex ecryptfs_daemon_hash_mux;
+
 static inline struct ecryptfs_file_info *
 ecryptfs_file_to_private(struct file *file)
 {
@@ -500,7 +531,7 @@ ecryptfs_set_dentry_lower_mnt(struct dentry *dentry, struct vfsmount *lower_mnt)
 }
 
 #define ecryptfs_printk(type, fmt, arg...) \
-        __ecryptfs_printk(type "%s: " fmt, __FUNCTION__, ## arg);
+        __ecryptfs_printk(type "%s: " fmt, __func__, ## arg);
 void __ecryptfs_printk(const char *fmt, ...);
 
 extern const struct file_operations ecryptfs_main_fops;
@@ -581,10 +612,13 @@ int
 ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
                  size_t size, int flags);
 int ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode);
-int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid);
-int ecryptfs_process_quit(uid_t uid, pid_t pid);
-int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid,
-                             pid_t pid, u32 seq);
+int ecryptfs_process_helo(unsigned int transport, uid_t euid,
+                         struct user_namespace *user_ns, struct pid *pid);
+int ecryptfs_process_quit(uid_t euid, struct user_namespace *user_ns,
+                         struct pid *pid);
+int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
+                             struct user_namespace *user_ns, struct pid *pid,
+                             u32 seq);
 int ecryptfs_send_message(unsigned int transport, char *data, int data_len,
                          struct ecryptfs_msg_ctx **msg_ctx);
 int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx,
@@ -593,14 +627,14 @@ int ecryptfs_init_messaging(unsigned int transport);
 void ecryptfs_release_messaging(unsigned int transport);
 
 int ecryptfs_send_netlink(char *data, int data_len,
-                         struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type,
-                         u16 msg_flags, pid_t daemon_pid);
+                         struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type,
+                         u16 msg_flags, struct pid *daemon_pid);
 int ecryptfs_init_netlink(void);
 void ecryptfs_release_netlink(void);
 
 int ecryptfs_send_connector(char *data, int data_len,
-                           struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type,
-                           u16 msg_flags, pid_t daemon_pid);
+                           struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type,
+                           u16 msg_flags, struct pid *daemon_pid);
 int ecryptfs_init_connector(void);
 void ecryptfs_release_connector(void);
 void
@@ -642,5 +676,21 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs,
                                     size_t offset_in_page, size_t size,
                                     struct inode *ecryptfs_inode);
 struct page *ecryptfs_get_locked_page(struct file *file, loff_t index);
+int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon);
+int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon, uid_t euid,
+                                struct user_namespace *user_ns);
+int ecryptfs_parse_packet_length(unsigned char *data, size_t *size,
+                                size_t *length_size);
+int ecryptfs_write_packet_length(char *dest, size_t size,
+                                size_t *packet_size_length);
+int ecryptfs_init_ecryptfs_miscdev(void);
+void ecryptfs_destroy_ecryptfs_miscdev(void);
+int ecryptfs_send_miscdev(char *data, size_t data_size,
+                         struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type,
+                         u16 msg_flags, struct ecryptfs_daemon *daemon);
+void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx);
+int
+ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid,
+                     struct user_namespace *user_ns, struct pid *pid);
 
 #endif /* #ifndef ECRYPTFS_KERNEL_H */
index 2b8f5ed4adea534063ae77259d366c426f9d5725..2258b8f654a62ff7f45e6df55cd3a501d1c5dc25 100644 (file)
@@ -195,7 +195,9 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
                file, ecryptfs_inode_to_private(inode)->lower_file);
        if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
                ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
+               mutex_lock(&crypt_stat->cs_mutex);
                crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
+               mutex_unlock(&crypt_stat->cs_mutex);
                rc = 0;
                goto out;
        }
index e2386115210105ecbbb01376a7290d0dd4dbe107..0a1397335a8eb49a245e81b1826607a5158a2685 100644 (file)
@@ -111,7 +111,7 @@ ecryptfs_do_create(struct inode *directory_inode,
 
        lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
        lower_dir_dentry = lock_parent(lower_dentry);
-       if (unlikely(IS_ERR(lower_dir_dentry))) {
+       if (IS_ERR(lower_dir_dentry)) {
                ecryptfs_printk(KERN_ERR, "Error locking directory of "
                                "dentry\n");
                rc = PTR_ERR(lower_dir_dentry);
@@ -121,7 +121,7 @@ ecryptfs_do_create(struct inode *directory_inode,
                                             ecryptfs_dentry, mode, nd);
        if (rc) {
                printk(KERN_ERR "%s: Failure to create dentry in lower fs; "
-                      "rc = [%d]\n", __FUNCTION__, rc);
+                      "rc = [%d]\n", __func__, rc);
                goto out_lock;
        }
        rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry,
@@ -908,7 +908,9 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
        if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
                ia->ia_valid &= ~ATTR_MODE;
 
+       mutex_lock(&lower_dentry->d_inode->i_mutex);
        rc = notify_change(lower_dentry, ia);
+       mutex_unlock(&lower_dentry->d_inode->i_mutex);
 out:
        fsstack_copy_attr_all(inode, lower_inode, NULL);
        return rc;
index 682b1b2482c26a062cefeaf924787242f89612d1..e82b457180be78706e4b829c4dec0ea15db82178 100644 (file)
@@ -65,7 +65,7 @@ static int process_request_key_err(long err_code)
 }
 
 /**
- * parse_packet_length
+ * ecryptfs_parse_packet_length
  * @data: Pointer to memory containing length at offset
  * @size: This function writes the decoded size to this memory
  *        address; zero on error
@@ -73,8 +73,8 @@ static int process_request_key_err(long err_code)
  *
  * Returns zero on success; non-zero on error
  */
-static int parse_packet_length(unsigned char *data, size_t *size,
-                              size_t *length_size)
+int ecryptfs_parse_packet_length(unsigned char *data, size_t *size,
+                                size_t *length_size)
 {
        int rc = 0;
 
@@ -105,7 +105,7 @@ out:
 }
 
 /**
- * write_packet_length
+ * ecryptfs_write_packet_length
  * @dest: The byte array target into which to write the length. Must
  *        have at least 5 bytes allocated.
  * @size: The length to write.
@@ -114,8 +114,8 @@ out:
  *
  * Returns zero on success; non-zero on error.
  */
-static int write_packet_length(char *dest, size_t size,
-                              size_t *packet_size_length)
+int ecryptfs_write_packet_length(char *dest, size_t size,
+                                size_t *packet_size_length)
 {
        int rc = 0;
 
@@ -162,8 +162,8 @@ write_tag_64_packet(char *signature, struct ecryptfs_session_key *session_key,
                goto out;
        }
        message[i++] = ECRYPTFS_TAG_64_PACKET_TYPE;
-       rc = write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX,
-                                &packet_size_len);
+       rc = ecryptfs_write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX,
+                                         &packet_size_len);
        if (rc) {
                ecryptfs_printk(KERN_ERR, "Error generating tag 64 packet "
                                "header; cannot generate packet length\n");
@@ -172,8 +172,9 @@ write_tag_64_packet(char *signature, struct ecryptfs_session_key *session_key,
        i += packet_size_len;
        memcpy(&message[i], signature, ECRYPTFS_SIG_SIZE_HEX);
        i += ECRYPTFS_SIG_SIZE_HEX;
-       rc = write_packet_length(&message[i], session_key->encrypted_key_size,
-                                &packet_size_len);
+       rc = ecryptfs_write_packet_length(&message[i],
+                                         session_key->encrypted_key_size,
+                                         &packet_size_len);
        if (rc) {
                ecryptfs_printk(KERN_ERR, "Error generating tag 64 packet "
                                "header; cannot generate packet length\n");
@@ -225,7 +226,7 @@ parse_tag_65_packet(struct ecryptfs_session_key *session_key, u8 *cipher_code,
                rc = -EIO;
                goto out;
        }
-       rc = parse_packet_length(&data[i], &m_size, &data_len);
+       rc = ecryptfs_parse_packet_length(&data[i], &m_size, &data_len);
        if (rc) {
                ecryptfs_printk(KERN_WARNING, "Error parsing packet length; "
                                "rc = [%d]\n", rc);
@@ -304,8 +305,8 @@ write_tag_66_packet(char *signature, u8 cipher_code,
                goto out;
        }
        message[i++] = ECRYPTFS_TAG_66_PACKET_TYPE;
-       rc = write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX,
-                                &packet_size_len);
+       rc = ecryptfs_write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX,
+                                         &packet_size_len);
        if (rc) {
                ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet "
                                "header; cannot generate packet length\n");
@@ -315,8 +316,8 @@ write_tag_66_packet(char *signature, u8 cipher_code,
        memcpy(&message[i], signature, ECRYPTFS_SIG_SIZE_HEX);
        i += ECRYPTFS_SIG_SIZE_HEX;
        /* The encrypted key includes 1 byte cipher code and 2 byte checksum */
-       rc = write_packet_length(&message[i], crypt_stat->key_size + 3,
-                                &packet_size_len);
+       rc = ecryptfs_write_packet_length(&message[i], crypt_stat->key_size + 3,
+                                         &packet_size_len);
        if (rc) {
                ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet "
                                "header; cannot generate packet length\n");
@@ -357,20 +358,25 @@ parse_tag_67_packet(struct ecryptfs_key_record *key_rec,
        /* verify that everything through the encrypted FEK size is present */
        if (message_len < 4) {
                rc = -EIO;
+               printk(KERN_ERR "%s: message_len is [%Zd]; minimum acceptable "
+                      "message length is [%d]\n", __func__, message_len, 4);
                goto out;
        }
        if (data[i++] != ECRYPTFS_TAG_67_PACKET_TYPE) {
-               ecryptfs_printk(KERN_ERR, "Type should be ECRYPTFS_TAG_67\n");
                rc = -EIO;
+               printk(KERN_ERR "%s: Type should be ECRYPTFS_TAG_67\n",
+                      __func__);
                goto out;
        }
        if (data[i++]) {
-               ecryptfs_printk(KERN_ERR, "Status indicator has non zero value"
-                               " [%d]\n", data[i-1]);
                rc = -EIO;
+               printk(KERN_ERR "%s: Status indicator has non zero "
+                      "value [%d]\n", __func__, data[i-1]);
+
                goto out;
        }
-       rc = parse_packet_length(&data[i], &key_rec->enc_key_size, &data_len);
+       rc = ecryptfs_parse_packet_length(&data[i], &key_rec->enc_key_size,
+                                         &data_len);
        if (rc) {
                ecryptfs_printk(KERN_WARNING, "Error parsing packet length; "
                                "rc = [%d]\n", rc);
@@ -378,17 +384,17 @@ parse_tag_67_packet(struct ecryptfs_key_record *key_rec,
        }
        i += data_len;
        if (message_len < (i + key_rec->enc_key_size)) {
-               ecryptfs_printk(KERN_ERR, "message_len [%d]; max len is [%d]\n",
-                               message_len, (i + key_rec->enc_key_size));
                rc = -EIO;
+               printk(KERN_ERR "%s: message_len [%Zd]; max len is [%Zd]\n",
+                      __func__, message_len, (i + key_rec->enc_key_size));
                goto out;
        }
        if (key_rec->enc_key_size > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) {
-               ecryptfs_printk(KERN_ERR, "Encrypted key_size [%d] larger than "
-                               "the maximum key size [%d]\n",
-                               key_rec->enc_key_size,
-                               ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES);
                rc = -EIO;
+               printk(KERN_ERR "%s: Encrypted key_size [%Zd] larger than "
+                      "the maximum key size [%d]\n", __func__,
+                      key_rec->enc_key_size,
+                      ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES);
                goto out;
        }
        memcpy(key_rec->enc_key, &data[i], key_rec->enc_key_size);
@@ -445,7 +451,7 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
        rc = write_tag_64_packet(auth_tok_sig, &(auth_tok->session_key),
                                 &netlink_message, &netlink_message_length);
        if (rc) {
-               ecryptfs_printk(KERN_ERR, "Failed to write tag 64 packet");
+               ecryptfs_printk(KERN_ERR, "Failed to write tag 64 packet\n");
                goto out;
        }
        rc = ecryptfs_send_message(ecryptfs_transport, netlink_message,
@@ -570,8 +576,8 @@ parse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat,
                goto out;
        }
        (*new_auth_tok) = &auth_tok_list_item->auth_tok;
-       rc = parse_packet_length(&data[(*packet_size)], &body_size,
-                                &length_size);
+       rc = ecryptfs_parse_packet_length(&data[(*packet_size)], &body_size,
+                                         &length_size);
        if (rc) {
                printk(KERN_WARNING "Error parsing packet length; "
                       "rc = [%d]\n", rc);
@@ -704,8 +710,8 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat,
                goto out;
        }
        (*new_auth_tok) = &auth_tok_list_item->auth_tok;
-       rc = parse_packet_length(&data[(*packet_size)], &body_size,
-                                &length_size);
+       rc = ecryptfs_parse_packet_length(&data[(*packet_size)], &body_size,
+                                         &length_size);
        if (rc) {
                printk(KERN_WARNING "Error parsing packet length; rc = [%d]\n",
                       rc);
@@ -852,8 +858,8 @@ parse_tag_11_packet(unsigned char *data, unsigned char *contents,
                rc = -EINVAL;
                goto out;
        }
-       rc = parse_packet_length(&data[(*packet_size)], &body_size,
-                                &length_size);
+       rc = ecryptfs_parse_packet_length(&data[(*packet_size)], &body_size,
+                                         &length_size);
        if (rc) {
                printk(KERN_WARNING "Invalid tag 11 packet format\n");
                goto out;
@@ -1405,8 +1411,8 @@ write_tag_1_packet(char *dest, size_t *remaining_bytes,
                        auth_tok->token.private_key.key_size;
        rc = pki_encrypt_session_key(auth_tok, crypt_stat, key_rec);
        if (rc) {
-               ecryptfs_printk(KERN_ERR, "Failed to encrypt session key "
-                               "via a pki");
+               printk(KERN_ERR "Failed to encrypt session key via a key "
+                      "module; rc = [%d]\n", rc);
                goto out;
        }
        if (ecryptfs_verbosity > 0) {
@@ -1430,8 +1436,9 @@ encrypted_session_key_set:
                goto out;
        }
        dest[(*packet_size)++] = ECRYPTFS_TAG_1_PACKET_TYPE;
-       rc = write_packet_length(&dest[(*packet_size)], (max_packet_size - 4),
-                                &packet_size_length);
+       rc = ecryptfs_write_packet_length(&dest[(*packet_size)],
+                                         (max_packet_size - 4),
+                                         &packet_size_length);
        if (rc) {
                ecryptfs_printk(KERN_ERR, "Error generating tag 1 packet "
                                "header; cannot generate packet length\n");
@@ -1489,8 +1496,9 @@ write_tag_11_packet(char *dest, size_t *remaining_bytes, char *contents,
                goto out;
        }
        dest[(*packet_length)++] = ECRYPTFS_TAG_11_PACKET_TYPE;
-       rc = write_packet_length(&dest[(*packet_length)],
-                                (max_packet_size - 4), &packet_size_length);
+       rc = ecryptfs_write_packet_length(&dest[(*packet_length)],
+                                         (max_packet_size - 4),
+                                         &packet_size_length);
        if (rc) {
                printk(KERN_ERR "Error generating tag 11 packet header; cannot "
                       "generate packet length. rc = [%d]\n", rc);
@@ -1682,8 +1690,9 @@ encrypted_session_key_set:
        dest[(*packet_size)++] = ECRYPTFS_TAG_3_PACKET_TYPE;
        /* Chop off the Tag 3 identifier(1) and Tag 3 packet size(3)
         * to get the number of octets in the actual Tag 3 packet */
-       rc = write_packet_length(&dest[(*packet_size)], (max_packet_size - 4),
-                                &packet_size_length);
+       rc = ecryptfs_write_packet_length(&dest[(*packet_size)],
+                                         (max_packet_size - 4),
+                                         &packet_size_length);
        if (rc) {
                printk(KERN_ERR "Error generating tag 3 packet header; cannot "
                       "generate packet length. rc = [%d]\n", rc);
index d25ac9500a92bd31282f477461161f7ac6cbfeb5..d603631601ebdd364d619b18efdcbafec8b4ac91 100644 (file)
@@ -219,7 +219,7 @@ int ecryptfs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
        if (rc) {
                printk(KERN_ERR "%s: Error attempting to initialize the "
                       "persistent file for the dentry with name [%s]; "
-                      "rc = [%d]\n", __FUNCTION__, dentry->d_name.name, rc);
+                      "rc = [%d]\n", __func__, dentry->d_name.name, rc);
                goto out;
        }
 out:
index 9cc2aec27b0dc5b8de698dd8779b0cb4e70682b8..1b5c20058acbeefddc1031f5700993da2e799c58 100644 (file)
@@ -1,7 +1,7 @@
 /**
  * eCryptfs: Linux filesystem encryption layer
  *
- * Copyright (C) 2004-2006 International Business Machines Corp.
+ * Copyright (C) 2004-2008 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
  *             Tyler Hicks <tyhicks@ou.edu>
  *
  * 02111-1307, USA.
  */
 #include <linux/sched.h>
+#include <linux/user_namespace.h>
+#include <linux/nsproxy.h>
 #include "ecryptfs_kernel.h"
 
 static LIST_HEAD(ecryptfs_msg_ctx_free_list);
 static LIST_HEAD(ecryptfs_msg_ctx_alloc_list);
 static struct mutex ecryptfs_msg_ctx_lists_mux;
 
-static struct hlist_head *ecryptfs_daemon_id_hash;
-static struct mutex ecryptfs_daemon_id_hash_mux;
+static struct hlist_head *ecryptfs_daemon_hash;
+struct mutex ecryptfs_daemon_hash_mux;
 static int ecryptfs_hash_buckets;
 #define ecryptfs_uid_hash(uid) \
         hash_long((unsigned long)uid, ecryptfs_hash_buckets)
 
-static unsigned int ecryptfs_msg_counter;
+static u32 ecryptfs_msg_counter;
 static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr;
 
 /**
@@ -40,9 +42,10 @@ static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr;
  * @msg_ctx: The context that was acquired from the free list
  *
  * Acquires a context element from the free list and locks the mutex
- * on the context.  Returns zero on success; non-zero on error or upon
- * failure to acquire a free context element.  Be sure to lock the
- * list mutex before calling.
+ * on the context.  Sets the msg_ctx task to current.  Returns zero on
+ * success; non-zero on error or upon failure to acquire a free
+ * context element.  Must be called with ecryptfs_msg_ctx_lists_mux
+ * held.
  */
 static int ecryptfs_acquire_free_msg_ctx(struct ecryptfs_msg_ctx **msg_ctx)
 {
@@ -50,11 +53,11 @@ static int ecryptfs_acquire_free_msg_ctx(struct ecryptfs_msg_ctx **msg_ctx)
        int rc;
 
        if (list_empty(&ecryptfs_msg_ctx_free_list)) {
-               ecryptfs_printk(KERN_WARNING, "The eCryptfs free "
-                               "context list is empty.  It may be helpful to "
-                               "specify the ecryptfs_message_buf_len "
-                               "parameter to be greater than the current "
-                               "value of [%d]\n", ecryptfs_message_buf_len);
+               printk(KERN_WARNING "%s: The eCryptfs free "
+                      "context list is empty.  It may be helpful to "
+                      "specify the ecryptfs_message_buf_len "
+                      "parameter to be greater than the current "
+                      "value of [%d]\n", __func__, ecryptfs_message_buf_len);
                rc = -ENOMEM;
                goto out;
        }
@@ -75,8 +78,7 @@ out:
  * ecryptfs_msg_ctx_free_to_alloc
  * @msg_ctx: The context to move from the free list to the alloc list
  *
- * Be sure to lock the list mutex and the context mutex before
- * calling.
+ * Must be called with ecryptfs_msg_ctx_lists_mux held.
  */
 static void ecryptfs_msg_ctx_free_to_alloc(struct ecryptfs_msg_ctx *msg_ctx)
 {
@@ -89,36 +91,39 @@ static void ecryptfs_msg_ctx_free_to_alloc(struct ecryptfs_msg_ctx *msg_ctx)
  * ecryptfs_msg_ctx_alloc_to_free
  * @msg_ctx: The context to move from the alloc list to the free list
  *
- * Be sure to lock the list mutex and the context mutex before
- * calling.
+ * Must be called with ecryptfs_msg_ctx_lists_mux held.
  */
-static void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx)
+void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx)
 {
        list_move(&(msg_ctx->node), &ecryptfs_msg_ctx_free_list);
        if (msg_ctx->msg)
                kfree(msg_ctx->msg);
+       msg_ctx->msg = NULL;
        msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_FREE;
 }
 
 /**
- * ecryptfs_find_daemon_id
- * @uid: The user id which maps to the desired daemon id
- * @id: If return value is zero, points to the desired daemon id
- *      pointer
+ * ecryptfs_find_daemon_by_euid
+ * @euid: The effective user id which maps to the desired daemon id
+ * @user_ns: The namespace in which @euid applies
+ * @daemon: If return value is zero, points to the desired daemon pointer
  *
- * Search the hash list for the given user id.  Returns zero if the
- * user id exists in the list; non-zero otherwise.  The daemon id hash
- * mutex should be held before calling this function.
+ * Must be called with ecryptfs_daemon_hash_mux held.
+ *
+ * Search the hash list for the given user id.
+ *
+ * Returns zero if the user id exists in the list; non-zero otherwise.
  */
-static int ecryptfs_find_daemon_id(uid_t uid, struct ecryptfs_daemon_id **id)
+int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon, uid_t euid,
+                                struct user_namespace *user_ns)
 {
        struct hlist_node *elem;
        int rc;
 
-       hlist_for_each_entry(*id, elem,
-                            &ecryptfs_daemon_id_hash[ecryptfs_uid_hash(uid)],
-                            id_chain) {
-               if ((*id)->uid == uid) {
+       hlist_for_each_entry(*daemon, elem,
+                            &ecryptfs_daemon_hash[ecryptfs_uid_hash(euid)],
+                            euid_chain) {
+               if ((*daemon)->euid == euid && (*daemon)->user_ns == user_ns) {
                        rc = 0;
                        goto out;
                }
@@ -128,181 +133,325 @@ out:
        return rc;
 }
 
-static int ecryptfs_send_raw_message(unsigned int transport, u16 msg_type,
-                                    pid_t pid)
+static int
+ecryptfs_send_message_locked(unsigned int transport, char *data, int data_len,
+                            u8 msg_type, struct ecryptfs_msg_ctx **msg_ctx);
+
+/**
+ * ecryptfs_send_raw_message
+ * @transport: Transport type
+ * @msg_type: Message type
+ * @daemon: Daemon struct for recipient of message
+ *
+ * A raw message is one that does not include an ecryptfs_message
+ * struct. It simply has a type.
+ *
+ * Must be called with ecryptfs_daemon_hash_mux held.
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+static int ecryptfs_send_raw_message(unsigned int transport, u8 msg_type,
+                                    struct ecryptfs_daemon *daemon)
 {
+       struct ecryptfs_msg_ctx *msg_ctx;
        int rc;
 
        switch(transport) {
        case ECRYPTFS_TRANSPORT_NETLINK:
-               rc = ecryptfs_send_netlink(NULL, 0, NULL, msg_type, 0, pid);
+               rc = ecryptfs_send_netlink(NULL, 0, NULL, msg_type, 0,
+                                          daemon->pid);
+               break;
+       case ECRYPTFS_TRANSPORT_MISCDEV:
+               rc = ecryptfs_send_message_locked(transport, NULL, 0, msg_type,
+                                                 &msg_ctx);
+               if (rc) {
+                       printk(KERN_ERR "%s: Error whilst attempting to send "
+                              "message via procfs; rc = [%d]\n", __func__, rc);
+                       goto out;
+               }
+               /* Raw messages are logically context-free (e.g., no
+                * reply is expected), so we set the state of the
+                * ecryptfs_msg_ctx object to indicate that it should
+                * be freed as soon as the transport sends out the message. */
+               mutex_lock(&msg_ctx->mux);
+               msg_ctx->state = ECRYPTFS_MSG_CTX_STATE_NO_REPLY;
+               mutex_unlock(&msg_ctx->mux);
                break;
        case ECRYPTFS_TRANSPORT_CONNECTOR:
        case ECRYPTFS_TRANSPORT_RELAYFS:
        default:
                rc = -ENOSYS;
        }
+out:
+       return rc;
+}
+
+/**
+ * ecryptfs_spawn_daemon - Create and initialize a new daemon struct
+ * @daemon: Pointer to set to newly allocated daemon struct
+ * @euid: Effective user id for the daemon
+ * @user_ns: The namespace in which @euid applies
+ * @pid: Process id for the daemon
+ *
+ * Must be called ceremoniously while in possession of
+ * ecryptfs_sacred_daemon_hash_mux
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+int
+ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid,
+                     struct user_namespace *user_ns, struct pid *pid)
+{
+       int rc = 0;
+
+       (*daemon) = kzalloc(sizeof(**daemon), GFP_KERNEL);
+       if (!(*daemon)) {
+               rc = -ENOMEM;
+               printk(KERN_ERR "%s: Failed to allocate [%Zd] bytes of "
+                      "GFP_KERNEL memory\n", __func__, sizeof(**daemon));
+               goto out;
+       }
+       (*daemon)->euid = euid;
+       (*daemon)->user_ns = get_user_ns(user_ns);
+       (*daemon)->pid = get_pid(pid);
+       (*daemon)->task = current;
+       mutex_init(&(*daemon)->mux);
+       INIT_LIST_HEAD(&(*daemon)->msg_ctx_out_queue);
+       init_waitqueue_head(&(*daemon)->wait);
+       (*daemon)->num_queued_msg_ctx = 0;
+       hlist_add_head(&(*daemon)->euid_chain,
+                      &ecryptfs_daemon_hash[ecryptfs_uid_hash(euid)]);
+out:
        return rc;
 }
 
 /**
  * ecryptfs_process_helo
  * @transport: The underlying transport (netlink, etc.)
- * @uid: The user ID owner of the message
+ * @euid: The user ID owner of the message
+ * @user_ns: The namespace in which @euid applies
  * @pid: The process ID for the userspace program that sent the
  *       message
  *
- * Adds the uid and pid values to the daemon id hash.  If a uid
+ * Adds the euid and pid values to the daemon euid hash.  If an euid
  * already has a daemon pid registered, the daemon will be
- * unregistered before the new daemon id is put into the hash list.
- * Returns zero after adding a new daemon id to the hash list;
+ * unregistered before the new daemon is put into the hash list.
+ * Returns zero after adding a new daemon to the hash list;
  * non-zero otherwise.
  */
-int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid)
+int ecryptfs_process_helo(unsigned int transport, uid_t euid,
+                         struct user_namespace *user_ns, struct pid *pid)
 {
-       struct ecryptfs_daemon_id *new_id;
-       struct ecryptfs_daemon_id *old_id;
+       struct ecryptfs_daemon *new_daemon;
+       struct ecryptfs_daemon *old_daemon;
        int rc;
 
-       mutex_lock(&ecryptfs_daemon_id_hash_mux);
-       new_id = kmalloc(sizeof(*new_id), GFP_KERNEL);
-       if (!new_id) {
-               rc = -ENOMEM;
-               ecryptfs_printk(KERN_ERR, "Failed to allocate memory; unable "
-                               "to register daemon [%d] for user [%d]\n",
-                               pid, uid);
-               goto unlock;
-       }
-       if (!ecryptfs_find_daemon_id(uid, &old_id)) {
+       mutex_lock(&ecryptfs_daemon_hash_mux);
+       rc = ecryptfs_find_daemon_by_euid(&old_daemon, euid, user_ns);
+       if (rc != 0) {
                printk(KERN_WARNING "Received request from user [%d] "
-                      "to register daemon [%d]; unregistering daemon "
-                      "[%d]\n", uid, pid, old_id->pid);
-               hlist_del(&old_id->id_chain);
-               rc = ecryptfs_send_raw_message(transport, ECRYPTFS_NLMSG_QUIT,
-                                              old_id->pid);
+                      "to register daemon [0x%p]; unregistering daemon "
+                      "[0x%p]\n", euid, pid, old_daemon->pid);
+               rc = ecryptfs_send_raw_message(transport, ECRYPTFS_MSG_QUIT,
+                                              old_daemon);
                if (rc)
                        printk(KERN_WARNING "Failed to send QUIT "
-                              "message to daemon [%d]; rc = [%d]\n",
-                              old_id->pid, rc);
-               kfree(old_id);
+                              "message to daemon [0x%p]; rc = [%d]\n",
+                              old_daemon->pid, rc);
+               hlist_del(&old_daemon->euid_chain);
+               kfree(old_daemon);
        }
-       new_id->uid = uid;
-       new_id->pid = pid;
-       hlist_add_head(&new_id->id_chain,
-                      &ecryptfs_daemon_id_hash[ecryptfs_uid_hash(uid)]);
-       rc = 0;
-unlock:
-       mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+       rc = ecryptfs_spawn_daemon(&new_daemon, euid, user_ns, pid);
+       if (rc)
+               printk(KERN_ERR "%s: The gods are displeased with this attempt "
+                      "to create a new daemon object for euid [%d]; pid "
+                      "[0x%p]; rc = [%d]\n", __func__, euid, pid, rc);
+       mutex_unlock(&ecryptfs_daemon_hash_mux);
+       return rc;
+}
+
+/**
+ * ecryptfs_exorcise_daemon - Destroy the daemon struct
+ *
+ * Must be called ceremoniously while in possession of
+ * ecryptfs_daemon_hash_mux and the daemon's own mux.
+ */
+int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon)
+{
+       struct ecryptfs_msg_ctx *msg_ctx, *msg_ctx_tmp;
+       int rc = 0;
+
+       mutex_lock(&daemon->mux);
+       if ((daemon->flags & ECRYPTFS_DAEMON_IN_READ)
+           || (daemon->flags & ECRYPTFS_DAEMON_IN_POLL)) {
+               rc = -EBUSY;
+               printk(KERN_WARNING "%s: Attempt to destroy daemon with pid "
+                      "[0x%p], but it is in the midst of a read or a poll\n",
+                      __func__, daemon->pid);
+               mutex_unlock(&daemon->mux);
+               goto out;
+       }
+       list_for_each_entry_safe(msg_ctx, msg_ctx_tmp,
+                                &daemon->msg_ctx_out_queue, daemon_out_list) {
+               list_del(&msg_ctx->daemon_out_list);
+               daemon->num_queued_msg_ctx--;
+               printk(KERN_WARNING "%s: Warning: dropping message that is in "
+                      "the out queue of a dying daemon\n", __func__);
+               ecryptfs_msg_ctx_alloc_to_free(msg_ctx);
+       }
+       hlist_del(&daemon->euid_chain);
+       if (daemon->task)
+               wake_up_process(daemon->task);
+       if (daemon->pid)
+               put_pid(daemon->pid);
+       if (daemon->user_ns)
+               put_user_ns(daemon->user_ns);
+       mutex_unlock(&daemon->mux);
+       memset(daemon, 0, sizeof(*daemon));
+       kfree(daemon);
+out:
        return rc;
 }
 
 /**
  * ecryptfs_process_quit
- * @uid: The user ID owner of the message
+ * @euid: The user ID owner of the message
+ * @user_ns: The namespace in which @euid applies
  * @pid: The process ID for the userspace program that sent the
  *       message
  *
- * Deletes the corresponding daemon id for the given uid and pid, if
+ * Deletes the corresponding daemon for the given euid and pid, if
  * it is the registered that is requesting the deletion. Returns zero
- * after deleting the desired daemon id; non-zero otherwise.
+ * after deleting the desired daemon; non-zero otherwise.
  */
-int ecryptfs_process_quit(uid_t uid, pid_t pid)
+int ecryptfs_process_quit(uid_t euid, struct user_namespace *user_ns,
+                         struct pid *pid)
 {
-       struct ecryptfs_daemon_id *id;
+       struct ecryptfs_daemon *daemon;
        int rc;
 
-       mutex_lock(&ecryptfs_daemon_id_hash_mux);
-       if (ecryptfs_find_daemon_id(uid, &id)) {
+       mutex_lock(&ecryptfs_daemon_hash_mux);
+       rc = ecryptfs_find_daemon_by_euid(&daemon, euid, user_ns);
+       if (rc || !daemon) {
                rc = -EINVAL;
-               ecryptfs_printk(KERN_ERR, "Received request from user [%d] to "
-                               "unregister unrecognized daemon [%d]\n", uid,
-                               pid);
-               goto unlock;
+               printk(KERN_ERR "Received request from user [%d] to "
+                      "unregister unrecognized daemon [0x%p]\n", euid, pid);
+               goto out_unlock;
        }
-       if (id->pid != pid) {
-               rc = -EINVAL;
-               ecryptfs_printk(KERN_WARNING, "Received request from user [%d] "
-                               "with pid [%d] to unregister daemon [%d]\n",
-                               uid, pid, id->pid);
-               goto unlock;
-       }
-       hlist_del(&id->id_chain);
-       kfree(id);
-       rc = 0;
-unlock:
-       mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+       rc = ecryptfs_exorcise_daemon(daemon);
+out_unlock:
+       mutex_unlock(&ecryptfs_daemon_hash_mux);
        return rc;
 }
 
 /**
  * ecryptfs_process_reponse
  * @msg: The ecryptfs message received; the caller should sanity check
- *       msg->data_len
+ *       msg->data_len and free the memory
  * @pid: The process ID of the userspace application that sent the
  *       message
- * @seq: The sequence number of the message
+ * @seq: The sequence number of the message; must match the sequence
+ *       number for the existing message context waiting for this
+ *       response
+ *
+ * Processes a response message after sending an operation request to
+ * userspace. Some other process is awaiting this response. Before
+ * sending out its first communications, the other process allocated a
+ * msg_ctx from the ecryptfs_msg_ctx_arr at a particular index. The
+ * response message contains this index so that we can copy over the
+ * response message into the msg_ctx that the process holds a
+ * reference to. The other process is going to wake up, check to see
+ * that msg_ctx->state == ECRYPTFS_MSG_CTX_STATE_DONE, and then
+ * proceed to read off and process the response message. Returns zero
+ * upon delivery to desired context element; non-zero upon delivery
+ * failure or error.
  *
- * Processes a response message after sending a operation request to
- * userspace. Returns zero upon delivery to desired context element;
- * non-zero upon delivery failure or error.
+ * Returns zero on success; non-zero otherwise
  */
-int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid,
-                             pid_t pid, u32 seq)
+int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
+                             struct user_namespace *user_ns, struct pid *pid,
+                             u32 seq)
 {
-       struct ecryptfs_daemon_id *id;
+       struct ecryptfs_daemon *daemon;
        struct ecryptfs_msg_ctx *msg_ctx;
-       int msg_size;
+       size_t msg_size;
+       struct nsproxy *nsproxy;
+       struct user_namespace *current_user_ns;
        int rc;
 
        if (msg->index >= ecryptfs_message_buf_len) {
                rc = -EINVAL;
-               ecryptfs_printk(KERN_ERR, "Attempt to reference "
-                               "context buffer at index [%d]; maximum "
-                               "allowable is [%d]\n", msg->index,
-                               (ecryptfs_message_buf_len - 1));
+               printk(KERN_ERR "%s: Attempt to reference "
+                      "context buffer at index [%d]; maximum "
+                      "allowable is [%d]\n", __func__, msg->index,
+                      (ecryptfs_message_buf_len - 1));
                goto out;
        }
        msg_ctx = &ecryptfs_msg_ctx_arr[msg->index];
        mutex_lock(&msg_ctx->mux);
-       if (ecryptfs_find_daemon_id(msg_ctx->task->euid, &id)) {
+       mutex_lock(&ecryptfs_daemon_hash_mux);
+       rcu_read_lock();
+       nsproxy = task_nsproxy(msg_ctx->task);
+       if (nsproxy == NULL) {
                rc = -EBADMSG;
-               ecryptfs_printk(KERN_WARNING, "User [%d] received a "
-                               "message response from process [%d] but does "
-                               "not have a registered daemon\n",
-                               msg_ctx->task->euid, pid);
+               printk(KERN_ERR "%s: Receiving process is a zombie. Dropping "
+                      "message.\n", __func__);
+               rcu_read_unlock();
+               mutex_unlock(&ecryptfs_daemon_hash_mux);
                goto wake_up;
        }
-       if (msg_ctx->task->euid != uid) {
+       current_user_ns = nsproxy->user_ns;
+       rc = ecryptfs_find_daemon_by_euid(&daemon, msg_ctx->task->euid,
+                                         current_user_ns);
+       rcu_read_unlock();
+       mutex_unlock(&ecryptfs_daemon_hash_mux);
+       if (rc) {
+               rc = -EBADMSG;
+               printk(KERN_WARNING "%s: User [%d] received a "
+                      "message response from process [0x%p] but does "
+                      "not have a registered daemon\n", __func__,
+                      msg_ctx->task->euid, pid);
+               goto wake_up;
+       }
+       if (msg_ctx->task->euid != euid) {
                rc = -EBADMSG;
-               ecryptfs_printk(KERN_WARNING, "Received message from user "
-                               "[%d]; expected message from user [%d]\n",
-                               uid, msg_ctx->task->euid);
+               printk(KERN_WARNING "%s: Received message from user "
+                      "[%d]; expected message from user [%d]\n", __func__,
+                      euid, msg_ctx->task->euid);
                goto unlock;
        }
-       if (id->pid != pid) {
+       if (current_user_ns != user_ns) {
                rc = -EBADMSG;
-               ecryptfs_printk(KERN_ERR, "User [%d] received a "
-                               "message response from an unrecognized "
-                               "process [%d]\n", msg_ctx->task->euid, pid);
+               printk(KERN_WARNING "%s: Received message from user_ns "
+                      "[0x%p]; expected message from user_ns [0x%p]\n",
+                      __func__, user_ns, nsproxy->user_ns);
+               goto unlock;
+       }
+       if (daemon->pid != pid) {
+               rc = -EBADMSG;
+               printk(KERN_ERR "%s: User [%d] sent a message response "
+                      "from an unrecognized process [0x%p]\n",
+                      __func__, msg_ctx->task->euid, pid);
                goto unlock;
        }
        if (msg_ctx->state != ECRYPTFS_MSG_CTX_STATE_PENDING) {
                rc = -EINVAL;
-               ecryptfs_printk(KERN_WARNING, "Desired context element is not "
-                               "pending a response\n");
+               printk(KERN_WARNING "%s: Desired context element is not "
+                      "pending a response\n", __func__);
                goto unlock;
        } else if (msg_ctx->counter != seq) {
                rc = -EINVAL;
-               ecryptfs_printk(KERN_WARNING, "Invalid message sequence; "
-                               "expected [%d]; received [%d]\n",
-                               msg_ctx->counter, seq);
+               printk(KERN_WARNING "%s: Invalid message sequence; "
+                      "expected [%d]; received [%d]\n", __func__,
+                      msg_ctx->counter, seq);
                goto unlock;
        }
-       msg_size = sizeof(*msg) + msg->data_len;
+       msg_size = (sizeof(*msg) + msg->data_len);
        msg_ctx->msg = kmalloc(msg_size, GFP_KERNEL);
        if (!msg_ctx->msg) {
                rc = -ENOMEM;
-               ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n");
+               printk(KERN_ERR "%s: Failed to allocate [%Zd] bytes of "
+                      "GFP_KERNEL memory\n", __func__, msg_size);
                goto unlock;
        }
        memcpy(msg_ctx->msg, msg, msg_size);
@@ -317,34 +466,38 @@ out:
 }
 
 /**
- * ecryptfs_send_message
+ * ecryptfs_send_message_locked
  * @transport: The transport over which to send the message (i.e.,
  *             netlink)
  * @data: The data to send
  * @data_len: The length of data
  * @msg_ctx: The message context allocated for the send
+ *
+ * Must be called with ecryptfs_daemon_hash_mux held.
+ *
+ * Returns zero on success; non-zero otherwise
  */
-int ecryptfs_send_message(unsigned int transport, char *data, int data_len,
-                         struct ecryptfs_msg_ctx **msg_ctx)
+static int
+ecryptfs_send_message_locked(unsigned int transport, char *data, int data_len,
+                            u8 msg_type, struct ecryptfs_msg_ctx **msg_ctx)
 {
-       struct ecryptfs_daemon_id *id;
+       struct ecryptfs_daemon *daemon;
        int rc;
 
-       mutex_lock(&ecryptfs_daemon_id_hash_mux);
-       if (ecryptfs_find_daemon_id(current->euid, &id)) {
-               mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+       rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
+                                         current->nsproxy->user_ns);
+       if (rc || !daemon) {
                rc = -ENOTCONN;
-               ecryptfs_printk(KERN_ERR, "User [%d] does not have a daemon "
-                               "registered\n", current->euid);
+               printk(KERN_ERR "%s: User [%d] does not have a daemon "
+                      "registered\n", __func__, current->euid);
                goto out;
        }
-       mutex_unlock(&ecryptfs_daemon_id_hash_mux);
        mutex_lock(&ecryptfs_msg_ctx_lists_mux);
        rc = ecryptfs_acquire_free_msg_ctx(msg_ctx);
        if (rc) {
                mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
-               ecryptfs_printk(KERN_WARNING, "Could not claim a free "
-                               "context element\n");
+               printk(KERN_WARNING "%s: Could not claim a free "
+                      "context element\n", __func__);
                goto out;
        }
        ecryptfs_msg_ctx_free_to_alloc(*msg_ctx);
@@ -352,22 +505,49 @@ int ecryptfs_send_message(unsigned int transport, char *data, int data_len,
        mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
        switch (transport) {
        case ECRYPTFS_TRANSPORT_NETLINK:
-               rc = ecryptfs_send_netlink(data, data_len, *msg_ctx,
-                                          ECRYPTFS_NLMSG_REQUEST, 0, id->pid);
+               rc = ecryptfs_send_netlink(data, data_len, *msg_ctx, msg_type,
+                                          0, daemon->pid);
+               break;
+       case ECRYPTFS_TRANSPORT_MISCDEV:
+               rc = ecryptfs_send_miscdev(data, data_len, *msg_ctx, msg_type,
+                                          0, daemon);
                break;
        case ECRYPTFS_TRANSPORT_CONNECTOR:
        case ECRYPTFS_TRANSPORT_RELAYFS:
        default:
                rc = -ENOSYS;
        }
-       if (rc) {
-               printk(KERN_ERR "Error attempting to send message to userspace "
-                      "daemon; rc = [%d]\n", rc);
-       }
+       if (rc)
+               printk(KERN_ERR "%s: Error attempting to send message to "
+                      "userspace daemon; rc = [%d]\n", __func__, rc);
 out:
        return rc;
 }
 
+/**
+ * ecryptfs_send_message
+ * @transport: The transport over which to send the message (i.e.,
+ *             netlink)
+ * @data: The data to send
+ * @data_len: The length of data
+ * @msg_ctx: The message context allocated for the send
+ *
+ * Grabs ecryptfs_daemon_hash_mux.
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+int ecryptfs_send_message(unsigned int transport, char *data, int data_len,
+                         struct ecryptfs_msg_ctx **msg_ctx)
+{
+       int rc;
+
+       mutex_lock(&ecryptfs_daemon_hash_mux);
+       rc = ecryptfs_send_message_locked(transport, data, data_len,
+                                         ECRYPTFS_MSG_REQUEST, msg_ctx);
+       mutex_unlock(&ecryptfs_daemon_hash_mux);
+       return rc;
+}
+
 /**
  * ecryptfs_wait_for_response
  * @msg_ctx: The context that was assigned when sending a message
@@ -377,7 +557,7 @@ out:
  * of time exceeds ecryptfs_message_wait_timeout.  If zero is
  * returned, msg will point to a valid message from userspace; a
  * non-zero value is returned upon failure to receive a message or an
- * error occurs.
+ * error occurs. Callee must free @msg on success.
  */
 int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx,
                               struct ecryptfs_message **msg)
@@ -413,32 +593,32 @@ int ecryptfs_init_messaging(unsigned int transport)
 
        if (ecryptfs_number_of_users > ECRYPTFS_MAX_NUM_USERS) {
                ecryptfs_number_of_users = ECRYPTFS_MAX_NUM_USERS;
-               ecryptfs_printk(KERN_WARNING, "Specified number of users is "
-                               "too large, defaulting to [%d] users\n",
-                               ecryptfs_number_of_users);
+               printk(KERN_WARNING "%s: Specified number of users is "
+                      "too large, defaulting to [%d] users\n", __func__,
+                      ecryptfs_number_of_users);
        }
-       mutex_init(&ecryptfs_daemon_id_hash_mux);
-       mutex_lock(&ecryptfs_daemon_id_hash_mux);
+       mutex_init(&ecryptfs_daemon_hash_mux);
+       mutex_lock(&ecryptfs_daemon_hash_mux);
        ecryptfs_hash_buckets = 1;
        while (ecryptfs_number_of_users >> ecryptfs_hash_buckets)
                ecryptfs_hash_buckets++;
-       ecryptfs_daemon_id_hash = kmalloc(sizeof(struct hlist_head)
-                                         * ecryptfs_hash_buckets, GFP_KERNEL);
-       if (!ecryptfs_daemon_id_hash) {
+       ecryptfs_daemon_hash = kmalloc((sizeof(struct hlist_head)
+                                       * ecryptfs_hash_buckets), GFP_KERNEL);
+       if (!ecryptfs_daemon_hash) {
                rc = -ENOMEM;
-               ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n");
-               mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+               printk(KERN_ERR "%s: Failed to allocate memory\n", __func__);
+               mutex_unlock(&ecryptfs_daemon_hash_mux);
                goto out;
        }
        for (i = 0; i < ecryptfs_hash_buckets; i++)
-               INIT_HLIST_HEAD(&ecryptfs_daemon_id_hash[i]);
-       mutex_unlock(&ecryptfs_daemon_id_hash_mux);
-
+               INIT_HLIST_HEAD(&ecryptfs_daemon_hash[i]);
+       mutex_unlock(&ecryptfs_daemon_hash_mux);
        ecryptfs_msg_ctx_arr = kmalloc((sizeof(struct ecryptfs_msg_ctx)
-                                     * ecryptfs_message_buf_len), GFP_KERNEL);
+                                       * ecryptfs_message_buf_len),
+                                      GFP_KERNEL);
        if (!ecryptfs_msg_ctx_arr) {
                rc = -ENOMEM;
-               ecryptfs_printk(KERN_ERR, "Failed to allocate memory\n");
+               printk(KERN_ERR "%s: Failed to allocate memory\n", __func__);
                goto out;
        }
        mutex_init(&ecryptfs_msg_ctx_lists_mux);
@@ -446,6 +626,7 @@ int ecryptfs_init_messaging(unsigned int transport)
        ecryptfs_msg_counter = 0;
        for (i = 0; i < ecryptfs_message_buf_len; i++) {
                INIT_LIST_HEAD(&ecryptfs_msg_ctx_arr[i].node);
+               INIT_LIST_HEAD(&ecryptfs_msg_ctx_arr[i].daemon_out_list);
                mutex_init(&ecryptfs_msg_ctx_arr[i].mux);
                mutex_lock(&ecryptfs_msg_ctx_arr[i].mux);
                ecryptfs_msg_ctx_arr[i].index = i;
@@ -464,6 +645,11 @@ int ecryptfs_init_messaging(unsigned int transport)
                if (rc)
                        ecryptfs_release_messaging(transport);
                break;
+       case ECRYPTFS_TRANSPORT_MISCDEV:
+               rc = ecryptfs_init_ecryptfs_miscdev();
+               if (rc)
+                       ecryptfs_release_messaging(transport);
+               break;
        case ECRYPTFS_TRANSPORT_CONNECTOR:
        case ECRYPTFS_TRANSPORT_RELAYFS:
        default:
@@ -488,27 +674,37 @@ void ecryptfs_release_messaging(unsigned int transport)
                kfree(ecryptfs_msg_ctx_arr);
                mutex_unlock(&ecryptfs_msg_ctx_lists_mux);
        }
-       if (ecryptfs_daemon_id_hash) {
+       if (ecryptfs_daemon_hash) {
                struct hlist_node *elem;
-               struct ecryptfs_daemon_id *id;
+               struct ecryptfs_daemon *daemon;
                int i;
 
-               mutex_lock(&ecryptfs_daemon_id_hash_mux);
+               mutex_lock(&ecryptfs_daemon_hash_mux);
                for (i = 0; i < ecryptfs_hash_buckets; i++) {
-                       hlist_for_each_entry(id, elem,
-                                            &ecryptfs_daemon_id_hash[i],
-                                            id_chain) {
-                               hlist_del(elem);
-                               kfree(id);
+                       int rc;
+
+                       hlist_for_each_entry(daemon, elem,
+                                            &ecryptfs_daemon_hash[i],
+                                            euid_chain) {
+                               rc = ecryptfs_exorcise_daemon(daemon);
+                               if (rc)
+                                       printk(KERN_ERR "%s: Error whilst "
+                                              "attempting to destroy daemon; "
+                                              "rc = [%d]. Dazed and confused, "
+                                              "but trying to continue.\n",
+                                              __func__, rc);
                        }
                }
-               kfree(ecryptfs_daemon_id_hash);
-               mutex_unlock(&ecryptfs_daemon_id_hash_mux);
+               kfree(ecryptfs_daemon_hash);
+               mutex_unlock(&ecryptfs_daemon_hash_mux);
        }
        switch(transport) {
        case ECRYPTFS_TRANSPORT_NETLINK:
                ecryptfs_release_netlink();
                break;
+       case ECRYPTFS_TRANSPORT_MISCDEV:
+               ecryptfs_destroy_ecryptfs_miscdev();
+               break;
        case ECRYPTFS_TRANSPORT_CONNECTOR:
        case ECRYPTFS_TRANSPORT_RELAYFS:
        default:
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c
new file mode 100644 (file)
index 0000000..788995e
--- /dev/null
@@ -0,0 +1,598 @@
+/**
+ * eCryptfs: Linux filesystem encryption layer
+ *
+ * Copyright (C) 2008 International Business Machines Corp.
+ *   Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * 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/fs.h>
+#include <linux/hash.h>
+#include <linux/random.h>
+#include <linux/miscdevice.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <linux/module.h>
+#include "ecryptfs_kernel.h"
+
+static atomic_t ecryptfs_num_miscdev_opens;
+
+/**
+ * ecryptfs_miscdev_poll
+ * @file: dev file (ignored)
+ * @pt: dev poll table (ignored)
+ *
+ * Returns the poll mask
+ */
+static unsigned int
+ecryptfs_miscdev_poll(struct file *file, poll_table *pt)
+{
+       struct ecryptfs_daemon *daemon;
+       unsigned int mask = 0;
+       int rc;
+
+       mutex_lock(&ecryptfs_daemon_hash_mux);
+       /* TODO: Just use file->private_data? */
+       rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
+                                         current->nsproxy->user_ns);
+       BUG_ON(rc || !daemon);
+       mutex_lock(&daemon->mux);
+       mutex_unlock(&ecryptfs_daemon_hash_mux);
+       if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
+               printk(KERN_WARNING "%s: Attempt to poll on zombified "
+                      "daemon\n", __func__);
+               goto out_unlock_daemon;
+       }
+       if (daemon->flags & ECRYPTFS_DAEMON_IN_READ)
+               goto out_unlock_daemon;
+       if (daemon->flags & ECRYPTFS_DAEMON_IN_POLL)
+               goto out_unlock_daemon;
+       daemon->flags |= ECRYPTFS_DAEMON_IN_POLL;
+       mutex_unlock(&daemon->mux);
+       poll_wait(file, &daemon->wait, pt);
+       mutex_lock(&daemon->mux);
+       if (!list_empty(&daemon->msg_ctx_out_queue))
+               mask |= POLLIN | POLLRDNORM;
+out_unlock_daemon:
+       daemon->flags &= ~ECRYPTFS_DAEMON_IN_POLL;
+       mutex_unlock(&daemon->mux);
+       return mask;
+}
+
+/**
+ * ecryptfs_miscdev_open
+ * @inode: inode of miscdev handle (ignored)
+ * @file: file for miscdev handle (ignored)
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+static int
+ecryptfs_miscdev_open(struct inode *inode, struct file *file)
+{
+       struct ecryptfs_daemon *daemon = NULL;
+       int rc;
+
+       mutex_lock(&ecryptfs_daemon_hash_mux);
+       rc = try_module_get(THIS_MODULE);
+       if (rc == 0) {
+               rc = -EIO;
+               printk(KERN_ERR "%s: Error attempting to increment module use "
+                      "count; rc = [%d]\n", __func__, rc);
+               goto out_unlock_daemon_list;
+       }
+       rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
+                                         current->nsproxy->user_ns);
+       if (rc || !daemon) {
+               rc = ecryptfs_spawn_daemon(&daemon, current->euid,
+                                          current->nsproxy->user_ns,
+                                          task_pid(current));
+               if (rc) {
+                       printk(KERN_ERR "%s: Error attempting to spawn daemon; "
+                              "rc = [%d]\n", __func__, rc);
+                       goto out_module_put_unlock_daemon_list;
+               }
+       }
+       mutex_lock(&daemon->mux);
+       if (daemon->pid != task_pid(current)) {
+               rc = -EINVAL;
+               printk(KERN_ERR "%s: pid [0x%p] has registered with euid [%d], "
+                      "but pid [0x%p] has attempted to open the handle "
+                      "instead\n", __func__, daemon->pid, daemon->euid,
+                      task_pid(current));
+               goto out_unlock_daemon;
+       }
+       if (daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN) {
+               rc = -EBUSY;
+               printk(KERN_ERR "%s: Miscellaneous device handle may only be "
+                      "opened once per daemon; pid [0x%p] already has this "
+                      "handle open\n", __func__, daemon->pid);
+               goto out_unlock_daemon;
+       }
+       daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN;
+       atomic_inc(&ecryptfs_num_miscdev_opens);
+out_unlock_daemon:
+       mutex_unlock(&daemon->mux);
+out_module_put_unlock_daemon_list:
+       if (rc)
+               module_put(THIS_MODULE);
+out_unlock_daemon_list:
+       mutex_unlock(&ecryptfs_daemon_hash_mux);
+       return rc;
+}
+
+/**
+ * ecryptfs_miscdev_release
+ * @inode: inode of fs/ecryptfs/euid handle (ignored)
+ * @file: file for fs/ecryptfs/euid handle (ignored)
+ *
+ * This keeps the daemon registered until the daemon sends another
+ * ioctl to fs/ecryptfs/ctl or until the kernel module unregisters.
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+static int
+ecryptfs_miscdev_release(struct inode *inode, struct file *file)
+{
+       struct ecryptfs_daemon *daemon = NULL;
+       int rc;
+
+       mutex_lock(&ecryptfs_daemon_hash_mux);
+       rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
+                                         current->nsproxy->user_ns);
+       BUG_ON(rc || !daemon);
+       mutex_lock(&daemon->mux);
+       BUG_ON(daemon->pid != task_pid(current));
+       BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN));
+       daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN;
+       atomic_dec(&ecryptfs_num_miscdev_opens);
+       mutex_unlock(&daemon->mux);
+       rc = ecryptfs_exorcise_daemon(daemon);
+       if (rc) {
+               printk(KERN_CRIT "%s: Fatal error whilst attempting to "
+                      "shut down daemon; rc = [%d]. Please report this "
+                      "bug.\n", __func__, rc);
+               BUG();
+       }
+       module_put(THIS_MODULE);
+       mutex_unlock(&ecryptfs_daemon_hash_mux);
+       return rc;
+}
+
+/**
+ * ecryptfs_send_miscdev
+ * @data: Data to send to daemon; may be NULL
+ * @data_size: Amount of data to send to daemon
+ * @msg_ctx: Message context, which is used to handle the reply. If
+ *           this is NULL, then we do not expect a reply.
+ * @msg_type: Type of message
+ * @msg_flags: Flags for message
+ * @daemon: eCryptfs daemon object
+ *
+ * Add msg_ctx to queue and then, if it exists, notify the blocked
+ * miscdevess about the data being available. Must be called with
+ * ecryptfs_daemon_hash_mux held.
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+int ecryptfs_send_miscdev(char *data, size_t data_size,
+                         struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type,
+                         u16 msg_flags, struct ecryptfs_daemon *daemon)
+{
+       int rc = 0;
+
+       mutex_lock(&msg_ctx->mux);
+       if (data) {
+               msg_ctx->msg = kmalloc((sizeof(*msg_ctx->msg) + data_size),
+                                      GFP_KERNEL);
+               if (!msg_ctx->msg) {
+                       rc = -ENOMEM;
+                       printk(KERN_ERR "%s: Out of memory whilst attempting "
+                              "to kmalloc(%Zd, GFP_KERNEL)\n", __func__,
+                              (sizeof(*msg_ctx->msg) + data_size));
+                       goto out_unlock;
+               }
+       } else
+               msg_ctx->msg = NULL;
+       msg_ctx->msg->index = msg_ctx->index;
+       msg_ctx->msg->data_len = data_size;
+       msg_ctx->type = msg_type;
+       if (data) {
+               memcpy(msg_ctx->msg->data, data, data_size);
+               msg_ctx->msg_size = (sizeof(*msg_ctx->msg) + data_size);
+       } else
+               msg_ctx->msg_size = 0;
+       mutex_lock(&daemon->mux);
+       list_add_tail(&msg_ctx->daemon_out_list, &daemon->msg_ctx_out_queue);
+       daemon->num_queued_msg_ctx++;
+       wake_up_interruptible(&daemon->wait);
+       mutex_unlock(&daemon->mux);
+out_unlock:
+       mutex_unlock(&msg_ctx->mux);
+       return rc;
+}
+
+/**
+ * ecryptfs_miscdev_read - format and send message from queue
+ * @file: fs/ecryptfs/euid miscdevfs handle (ignored)
+ * @buf: User buffer into which to copy the next message on the daemon queue
+ * @count: Amount of space available in @buf
+ * @ppos: Offset in file (ignored)
+ *
+ * Pulls the most recent message from the daemon queue, formats it for
+ * being sent via a miscdevfs handle, and copies it into @buf
+ *
+ * Returns the number of bytes copied into the user buffer
+ */
+static ssize_t
+ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
+                     loff_t *ppos)
+{
+       struct ecryptfs_daemon *daemon;
+       struct ecryptfs_msg_ctx *msg_ctx;
+       size_t packet_length_size;
+       u32 counter_nbo;
+       char packet_length[3];
+       size_t i;
+       size_t total_length;
+       int rc;
+
+       mutex_lock(&ecryptfs_daemon_hash_mux);
+       /* TODO: Just use file->private_data? */
+       rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid,
+                                         current->nsproxy->user_ns);
+       BUG_ON(rc || !daemon);
+       mutex_lock(&daemon->mux);
+       if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
+               rc = 0;
+               printk(KERN_WARNING "%s: Attempt to read from zombified "
+                      "daemon\n", __func__);
+               goto out_unlock_daemon;
+       }
+       if (daemon->flags & ECRYPTFS_DAEMON_IN_READ) {
+               rc = 0;
+               goto out_unlock_daemon;
+       }
+       /* This daemon will not go away so long as this flag is set */
+       daemon->flags |= ECRYPTFS_DAEMON_IN_READ;
+       mutex_unlock(&ecryptfs_daemon_hash_mux);
+check_list:
+       if (list_empty(&daemon->msg_ctx_out_queue)) {
+               mutex_unlock(&daemon->mux);
+               rc = wait_event_interruptible(
+                       daemon->wait, !list_empty(&daemon->msg_ctx_out_queue));
+               mutex_lock(&daemon->mux);
+               if (rc < 0) {
+                       rc = 0;
+                       goto out_unlock_daemon;
+               }
+       }
+       if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
+               rc = 0;
+               goto out_unlock_daemon;
+       }
+       if (list_empty(&daemon->msg_ctx_out_queue)) {
+               /* Something else jumped in since the
+                * wait_event_interruptable() and removed the
+                * message from the queue; try again */
+               goto check_list;
+       }
+       BUG_ON(current->euid != daemon->euid);
+       BUG_ON(current->nsproxy->user_ns != daemon->user_ns);
+       BUG_ON(task_pid(current) != daemon->pid);
+       msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue,
+                                  struct ecryptfs_msg_ctx, daemon_out_list);
+       BUG_ON(!msg_ctx);
+       mutex_lock(&msg_ctx->mux);
+       if (msg_ctx->msg) {
+               rc = ecryptfs_write_packet_length(packet_length,
+                                                 msg_ctx->msg_size,
+                                                 &packet_length_size);
+               if (rc) {
+                       rc = 0;
+                       printk(KERN_WARNING "%s: Error writing packet length; "
+                              "rc = [%d]\n", __func__, rc);
+                       goto out_unlock_msg_ctx;
+               }
+       } else {
+               packet_length_size = 0;
+               msg_ctx->msg_size = 0;
+       }
+       /* miscdevfs packet format:
+        *  Octet 0: Type
+        *  Octets 1-4: network byte order msg_ctx->counter
+        *  Octets 5-N0: Size of struct ecryptfs_message to follow
+        *  Octets N0-N1: struct ecryptfs_message (including data)
+        *
+        *  Octets 5-N1 not written if the packet type does not
+        *  include a message */
+       total_length = (1 + 4 + packet_length_size + msg_ctx->msg_size);
+       if (count < total_length) {
+               rc = 0;
+               printk(KERN_WARNING "%s: Only given user buffer of "
+                      "size [%Zd], but we need [%Zd] to read the "
+                      "pending message\n", __func__, count, total_length);
+               goto out_unlock_msg_ctx;
+       }
+       i = 0;
+       buf[i++] = msg_ctx->type;
+       counter_nbo = cpu_to_be32(msg_ctx->counter);
+       memcpy(&buf[i], (char *)&counter_nbo, 4);
+       i += 4;
+       if (msg_ctx->msg) {
+               memcpy(&buf[i], packet_length, packet_length_size);
+               i += packet_length_size;
+               rc = copy_to_user(&buf[i], msg_ctx->msg, msg_ctx->msg_size);
+               if (rc) {
+                       printk(KERN_ERR "%s: copy_to_user returned error "
+                              "[%d]\n", __func__, rc);
+                       goto out_unlock_msg_ctx;
+               }
+               i += msg_ctx->msg_size;
+       }
+       rc = i;
+       list_del(&msg_ctx->daemon_out_list);
+       kfree(msg_ctx->msg);
+       msg_ctx->msg = NULL;
+       /* We do not expect a reply from the userspace daemon for any
+        * message type other than ECRYPTFS_MSG_REQUEST */
+       if (msg_ctx->type != ECRYPTFS_MSG_REQUEST)
+               ecryptfs_msg_ctx_alloc_to_free(msg_ctx);
+out_unlock_msg_ctx:
+       mutex_unlock(&msg_ctx->mux);
+out_unlock_daemon:
+       daemon->flags &= ~ECRYPTFS_DAEMON_IN_READ;
+       mutex_unlock(&daemon->mux);
+       return rc;
+}
+
+/**
+ * ecryptfs_miscdev_helo
+ * @euid: effective user id of miscdevess sending helo packet
+ * @user_ns: The namespace in which @euid applies
+ * @pid: miscdevess id of miscdevess sending helo packet
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+static int ecryptfs_miscdev_helo(uid_t euid, struct user_namespace *user_ns,
+                                struct pid *pid)
+{
+       int rc;
+
+       rc = ecryptfs_process_helo(ECRYPTFS_TRANSPORT_MISCDEV, euid, user_ns,
+                                  pid);
+       if (rc)
+               printk(KERN_WARNING "Error processing HELO; rc = [%d]\n", rc);
+       return rc;
+}
+
+/**
+ * ecryptfs_miscdev_quit
+ * @euid: effective user id of miscdevess sending quit packet
+ * @user_ns: The namespace in which @euid applies
+ * @pid: miscdevess id of miscdevess sending quit packet
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+static int ecryptfs_miscdev_quit(uid_t euid, struct user_namespace *user_ns,
+                                struct pid *pid)
+{
+       int rc;
+
+       rc = ecryptfs_process_quit(euid, user_ns, pid);
+       if (rc)
+               printk(KERN_WARNING
+                      "Error processing QUIT message; rc = [%d]\n", rc);
+       return rc;
+}
+
+/**
+ * ecryptfs_miscdev_response - miscdevess response to message previously sent to daemon
+ * @data: Bytes comprising struct ecryptfs_message
+ * @data_size: sizeof(struct ecryptfs_message) + data len
+ * @euid: Effective user id of miscdevess sending the miscdev response
+ * @user_ns: The namespace in which @euid applies
+ * @pid: Miscdevess id of miscdevess sending the miscdev response
+ * @seq: Sequence number for miscdev response packet
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+static int ecryptfs_miscdev_response(char *data, size_t data_size,
+                                    uid_t euid, struct user_namespace *user_ns,
+                                    struct pid *pid, u32 seq)
+{
+       struct ecryptfs_message *msg = (struct ecryptfs_message *)data;
+       int rc;
+
+       if ((sizeof(*msg) + msg->data_len) != data_size) {
+               printk(KERN_WARNING "%s: (sizeof(*msg) + msg->data_len) = "
+                      "[%Zd]; data_size = [%Zd]. Invalid packet.\n", __func__,
+                      (sizeof(*msg) + msg->data_len), data_size);
+               rc = -EINVAL;
+               goto out;
+       }
+       rc = ecryptfs_process_response(msg, euid, user_ns, pid, seq);
+       if (rc)
+               printk(KERN_ERR
+                      "Error processing response message; rc = [%d]\n", rc);
+out:
+       return rc;
+}
+
+/**
+ * ecryptfs_miscdev_write - handle write to daemon miscdev handle
+ * @file: File for misc dev handle (ignored)
+ * @buf: Buffer containing user data
+ * @count: Amount of data in @buf
+ * @ppos: Pointer to offset in file (ignored)
+ *
+ * miscdevfs packet format:
+ *  Octet 0: Type
+ *  Octets 1-4: network byte order msg_ctx->counter (0's for non-response)
+ *  Octets 5-N0: Size of struct ecryptfs_message to follow
+ *  Octets N0-N1: struct ecryptfs_message (including data)
+ *
+ * Returns the number of bytes read from @buf
+ */
+static ssize_t
+ecryptfs_miscdev_write(struct file *file, const char __user *buf,
+                      size_t count, loff_t *ppos)
+{
+       u32 counter_nbo, seq;
+       size_t packet_size, packet_size_length, i;
+       ssize_t sz = 0;
+       char *data;
+       int rc;
+
+       if (count == 0)
+               goto out;
+       data = kmalloc(count, GFP_KERNEL);
+       if (!data) {
+               printk(KERN_ERR "%s: Out of memory whilst attempting to "
+                      "kmalloc([%Zd], GFP_KERNEL)\n", __func__, count);
+               goto out;
+       }
+       rc = copy_from_user(data, buf, count);
+       if (rc) {
+               printk(KERN_ERR "%s: copy_from_user returned error [%d]\n",
+                      __func__, rc);
+               goto out_free;
+       }
+       sz = count;
+       i = 0;
+       switch (data[i++]) {
+       case ECRYPTFS_MSG_RESPONSE:
+               if (count < (1 + 4 + 1 + sizeof(struct ecryptfs_message))) {
+                       printk(KERN_WARNING "%s: Minimum acceptable packet "
+                              "size is [%Zd], but amount of data written is "
+                              "only [%Zd]. Discarding response packet.\n",
+                              __func__,
+                              (1 + 4 + 1 + sizeof(struct ecryptfs_message)),
+                              count);
+                       goto out_free;
+               }
+               memcpy((char *)&counter_nbo, &data[i], 4);
+               seq = be32_to_cpu(counter_nbo);
+               i += 4;
+               rc = ecryptfs_parse_packet_length(&data[i], &packet_size,
+                                                 &packet_size_length);
+               if (rc) {
+                       printk(KERN_WARNING "%s: Error parsing packet length; "
+                              "rc = [%d]\n", __func__, rc);
+                       goto out_free;
+               }
+               i += packet_size_length;
+               if ((1 + 4 + packet_size_length + packet_size) != count) {
+                       printk(KERN_WARNING "%s: (1 + packet_size_length([%Zd])"
+                              " + packet_size([%Zd]))([%Zd]) != "
+                              "count([%Zd]). Invalid packet format.\n",
+                              __func__, packet_size_length, packet_size,
+                              (1 + packet_size_length + packet_size), count);
+                       goto out_free;
+               }
+               rc = ecryptfs_miscdev_response(&data[i], packet_size,
+                                              current->euid,
+                                              current->nsproxy->user_ns,
+                                              task_pid(current), seq);
+               if (rc)
+                       printk(KERN_WARNING "%s: Failed to deliver miscdev "
+                              "response to requesting operation; rc = [%d]\n",
+                              __func__, rc);
+               break;
+       case ECRYPTFS_MSG_HELO:
+               rc = ecryptfs_miscdev_helo(current->euid,
+                                          current->nsproxy->user_ns,
+                                          task_pid(current));
+               if (rc) {
+                       printk(KERN_ERR "%s: Error attempting to process "
+                              "helo from pid [0x%p]; rc = [%d]\n", __func__,
+                              task_pid(current), rc);
+                       goto out_free;
+               }
+               break;
+       case ECRYPTFS_MSG_QUIT:
+               rc = ecryptfs_miscdev_quit(current->euid,
+                                          current->nsproxy->user_ns,
+                                          task_pid(current));
+               if (rc) {
+                       printk(KERN_ERR "%s: Error attempting to process "
+                              "quit from pid [0x%p]; rc = [%d]\n", __func__,
+                              task_pid(current), rc);
+                       goto out_free;
+               }
+               break;
+       default:
+               ecryptfs_printk(KERN_WARNING, "Dropping miscdev "
+                               "message of unrecognized type [%d]\n",
+                               data[0]);
+               break;
+       }
+out_free:
+       kfree(data);
+out:
+       return sz;
+}
+
+
+static const struct file_operations ecryptfs_miscdev_fops = {
+       .open    = ecryptfs_miscdev_open,
+       .poll    = ecryptfs_miscdev_poll,
+       .read    = ecryptfs_miscdev_read,
+       .write   = ecryptfs_miscdev_write,
+       .release = ecryptfs_miscdev_release,
+};
+
+static struct miscdevice ecryptfs_miscdev = {
+       .minor = MISC_DYNAMIC_MINOR,
+       .name  = "ecryptfs",
+       .fops  = &ecryptfs_miscdev_fops
+};
+
+/**
+ * ecryptfs_init_ecryptfs_miscdev
+ *
+ * Messages sent to the userspace daemon from the kernel are placed on
+ * a queue associated with the daemon. The next read against the
+ * miscdev handle by that daemon will return the oldest message placed
+ * on the message queue for the daemon.
+ *
+ * Returns zero on success; non-zero otherwise
+ */
+int ecryptfs_init_ecryptfs_miscdev(void)
+{
+       int rc;
+
+       atomic_set(&ecryptfs_num_miscdev_opens, 0);
+       mutex_lock(&ecryptfs_daemon_hash_mux);
+       rc = misc_register(&ecryptfs_miscdev);
+       if (rc)
+               printk(KERN_ERR "%s: Failed to register miscellaneous device "
+                      "for communications with userspace daemons; rc = [%d]\n",
+                      __func__, rc);
+       mutex_unlock(&ecryptfs_daemon_hash_mux);
+       return rc;
+}
+
+/**
+ * ecryptfs_destroy_ecryptfs_miscdev
+ *
+ * All of the daemons must be exorcised prior to calling this
+ * function.
+ */
+void ecryptfs_destroy_ecryptfs_miscdev(void)
+{
+       BUG_ON(atomic_read(&ecryptfs_num_miscdev_opens) != 0);
+       misc_deregister(&ecryptfs_miscdev);
+}
index 6df1debdccce14aabbf0e63193b66ec0c8366d3e..2b6fe1e6e8ba38d85f5e6b16e63bd8d55804a35a 100644 (file)
@@ -153,7 +153,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
                        flush_dcache_page(page);
                        if (rc) {
                                printk(KERN_ERR "%s: Error reading xattr "
-                                      "region; rc = [%d]\n", __FUNCTION__, rc);
+                                      "region; rc = [%d]\n", __func__, rc);
                                goto out;
                        }
                } else {
@@ -169,7 +169,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
                        if (rc) {
                                printk(KERN_ERR "%s: Error attempting to read "
                                       "extent at offset [%lld] in the lower "
-                                      "file; rc = [%d]\n", __FUNCTION__,
+                                      "file; rc = [%d]\n", __func__,
                                       lower_offset, rc);
                                goto out;
                        }
@@ -212,7 +212,7 @@ static int ecryptfs_readpage(struct file *file, struct page *page)
                                       "the encrypted content from the lower "
                                       "file whilst inserting the metadata "
                                       "from the xattr into the header; rc = "
-                                      "[%d]\n", __FUNCTION__, rc);
+                                      "[%d]\n", __func__, rc);
                                goto out;
                        }
 
@@ -293,7 +293,7 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
                        if (rc) {
                                printk(KERN_ERR "%s: Error attemping to read "
                                       "lower page segment; rc = [%d]\n",
-                                      __FUNCTION__, rc);
+                                      __func__, rc);
                                ClearPageUptodate(page);
                                goto out;
                        } else
@@ -308,7 +308,7 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
                                               "from the lower file whilst "
                                               "inserting the metadata from "
                                               "the xattr into the header; rc "
-                                              "= [%d]\n", __FUNCTION__, rc);
+                                              "= [%d]\n", __func__, rc);
                                        ClearPageUptodate(page);
                                        goto out;
                                }
@@ -320,7 +320,7 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
                                if (rc) {
                                        printk(KERN_ERR "%s: Error reading "
                                               "page; rc = [%d]\n",
-                                              __FUNCTION__, rc);
+                                              __func__, rc);
                                        ClearPageUptodate(page);
                                        goto out;
                                }
@@ -331,7 +331,7 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
                        if (rc) {
                                printk(KERN_ERR "%s: Error decrypting page "
                                       "at index [%ld]; rc = [%d]\n",
-                                      __FUNCTION__, page->index, rc);
+                                      __func__, page->index, rc);
                                ClearPageUptodate(page);
                                goto out;
                        }
@@ -348,7 +348,7 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
                        if (rc) {
                                printk(KERN_ERR "%s: Error on attempt to "
                                       "truncate to (higher) offset [%lld];"
-                                      " rc = [%d]\n", __FUNCTION__,
+                                      " rc = [%d]\n", __func__,
                                       prev_page_end_size, rc);
                                goto out;
                        }
@@ -389,7 +389,7 @@ static int ecryptfs_write_inode_size_to_header(struct inode *ecryptfs_inode)
        kfree(file_size_virt);
        if (rc)
                printk(KERN_ERR "%s: Error writing file size to header; "
-                      "rc = [%d]\n", __FUNCTION__, rc);
+                      "rc = [%d]\n", __func__, rc);
 out:
        return rc;
 }
index f638a698dc525350bc44054f567217d52c0fca71..e0abad62b39535fb8d98368266707af464b050be 100644 (file)
@@ -44,8 +44,8 @@ static struct sock *ecryptfs_nl_sock;
  * upon sending the message; non-zero upon error.
  */
 int ecryptfs_send_netlink(char *data, int data_len,
-                         struct ecryptfs_msg_ctx *msg_ctx, u16 msg_type,
-                         u16 msg_flags, pid_t daemon_pid)
+                         struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type,
+                         u16 msg_flags, struct pid *daemon_pid)
 {
        struct sk_buff *skb;
        struct nlmsghdr *nlh;
@@ -60,7 +60,7 @@ int ecryptfs_send_netlink(char *data, int data_len,
                ecryptfs_printk(KERN_ERR, "Failed to allocate socket buffer\n");
                goto out;
        }
-       nlh = NLMSG_PUT(skb, daemon_pid, msg_ctx ? msg_ctx->counter : 0,
+       nlh = NLMSG_PUT(skb, pid_nr(daemon_pid), msg_ctx ? msg_ctx->counter : 0,
                        msg_type, payload_len);
        nlh->nlmsg_flags = msg_flags;
        if (msg_ctx && payload_len) {
@@ -69,7 +69,7 @@ int ecryptfs_send_netlink(char *data, int data_len,
                msg->data_len = data_len;
                memcpy(msg->data, data, data_len);
        }
-       rc = netlink_unicast(ecryptfs_nl_sock, skb, daemon_pid, 0);
+       rc = netlink_unicast(ecryptfs_nl_sock, skb, pid_nr(daemon_pid), 0);
        if (rc < 0) {
                ecryptfs_printk(KERN_ERR, "Failed to send eCryptfs netlink "
                                "message; rc = [%d]\n", rc);
@@ -99,6 +99,7 @@ static int ecryptfs_process_nl_response(struct sk_buff *skb)
 {
        struct nlmsghdr *nlh = nlmsg_hdr(skb);
        struct ecryptfs_message *msg = NLMSG_DATA(nlh);
+       struct pid *pid;
        int rc;
 
        if (skb->len - NLMSG_HDRLEN - sizeof(*msg) != msg->data_len) {
@@ -107,8 +108,10 @@ static int ecryptfs_process_nl_response(struct sk_buff *skb)
                                "incorrectly specified data length\n");
                goto out;
        }
-       rc = ecryptfs_process_response(msg, NETLINK_CREDS(skb)->uid,
-                                      NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq);
+       pid = find_get_pid(NETLINK_CREDS(skb)->pid);
+       rc = ecryptfs_process_response(msg, NETLINK_CREDS(skb)->uid, NULL,
+                                      pid, nlh->nlmsg_seq);
+       put_pid(pid);
        if (rc)
                printk(KERN_ERR
                       "Error processing response message; rc = [%d]\n", rc);
@@ -126,11 +129,13 @@ out:
  */
 static int ecryptfs_process_nl_helo(struct sk_buff *skb)
 {
+       struct pid *pid;
        int rc;
 
+       pid = find_get_pid(NETLINK_CREDS(skb)->pid);
        rc = ecryptfs_process_helo(ECRYPTFS_TRANSPORT_NETLINK,
-                                  NETLINK_CREDS(skb)->uid,
-                                  NETLINK_CREDS(skb)->pid);
+                                  NETLINK_CREDS(skb)->uid, NULL, pid);
+       put_pid(pid);
        if (rc)
                printk(KERN_WARNING "Error processing HELO; rc = [%d]\n", rc);
        return rc;
@@ -147,10 +152,12 @@ static int ecryptfs_process_nl_helo(struct sk_buff *skb)
  */
 static int ecryptfs_process_nl_quit(struct sk_buff *skb)
 {
+       struct pid *pid;
        int rc;
 
-       rc = ecryptfs_process_quit(NETLINK_CREDS(skb)->uid,
-                                  NETLINK_CREDS(skb)->pid);
+       pid = find_get_pid(NETLINK_CREDS(skb)->pid);
+       rc = ecryptfs_process_quit(NETLINK_CREDS(skb)->uid, NULL, pid);
+       put_pid(pid);
        if (rc)
                printk(KERN_WARNING
                       "Error processing QUIT message; rc = [%d]\n", rc);
@@ -176,20 +183,20 @@ static void ecryptfs_receive_nl_message(struct sk_buff *skb)
                goto free;
        }
        switch (nlh->nlmsg_type) {
-               case ECRYPTFS_NLMSG_RESPONSE:
+               case ECRYPTFS_MSG_RESPONSE:
                        if (ecryptfs_process_nl_response(skb)) {
                                ecryptfs_printk(KERN_WARNING, "Failed to "
                                                "deliver netlink response to "
                                                "requesting operation\n");
                        }
                        break;
-               case ECRYPTFS_NLMSG_HELO:
+               case ECRYPTFS_MSG_HELO:
                        if (ecryptfs_process_nl_helo(skb)) {
                                ecryptfs_printk(KERN_WARNING, "Failed to "
                                                "fulfill HELO request\n");
                        }
                        break;
-               case ECRYPTFS_NLMSG_QUIT:
+               case ECRYPTFS_MSG_QUIT:
                        if (ecryptfs_process_nl_quit(skb)) {
                                ecryptfs_printk(KERN_WARNING, "Failed to "
                                                "fulfill QUIT request\n");
index 0c4928623bbc414f7f0a4861e4dc727bfcdf132f..ebf55150be56cdb26b6fab83990026fadaa71aaf 100644 (file)
@@ -55,7 +55,7 @@ int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
        set_fs(fs_save);
        if (octets_written < 0) {
                printk(KERN_ERR "%s: octets_written = [%td]; "
-                      "expected [%td]\n", __FUNCTION__, octets_written, size);
+                      "expected [%td]\n", __func__, octets_written, size);
                rc = -EINVAL;
        }
        mutex_unlock(&inode_info->lower_file_mutex);
@@ -153,7 +153,7 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
                        rc = PTR_ERR(ecryptfs_page);
                        printk(KERN_ERR "%s: Error getting page at "
                               "index [%ld] from eCryptfs inode "
-                              "mapping; rc = [%d]\n", __FUNCTION__,
+                              "mapping; rc = [%d]\n", __func__,
                               ecryptfs_page_idx, rc);
                        goto out;
                }
@@ -165,7 +165,7 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
                        if (rc) {
                                printk(KERN_ERR "%s: Error decrypting "
                                       "page; rc = [%d]\n",
-                                      __FUNCTION__, rc);
+                                      __func__, rc);
                                ClearPageUptodate(ecryptfs_page);
                                page_cache_release(ecryptfs_page);
                                goto out;
@@ -202,7 +202,7 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
                page_cache_release(ecryptfs_page);
                if (rc) {
                        printk(KERN_ERR "%s: Error encrypting "
-                              "page; rc = [%d]\n", __FUNCTION__, rc);
+                              "page; rc = [%d]\n", __func__, rc);
                        goto out;
                }
                pos += num_bytes;
@@ -254,7 +254,7 @@ int ecryptfs_read_lower(char *data, loff_t offset, size_t size,
        set_fs(fs_save);
        if (octets_read < 0) {
                printk(KERN_ERR "%s: octets_read = [%td]; "
-                      "expected [%td]\n", __FUNCTION__, octets_read, size);
+                      "expected [%td]\n", __func__, octets_read, size);
                rc = -EINVAL;
        }
        mutex_unlock(&inode_info->lower_file_mutex);
@@ -327,7 +327,7 @@ int ecryptfs_read(char *data, loff_t offset, size_t size,
                printk(KERN_ERR "%s: Attempt to read data past the end of the "
                        "file; offset = [%lld]; size = [%td]; "
                       "ecryptfs_file_size = [%lld]\n",
-                      __FUNCTION__, offset, size, ecryptfs_file_size);
+                      __func__, offset, size, ecryptfs_file_size);
                goto out;
        }
        pos = offset;
@@ -345,14 +345,14 @@ int ecryptfs_read(char *data, loff_t offset, size_t size,
                        rc = PTR_ERR(ecryptfs_page);
                        printk(KERN_ERR "%s: Error getting page at "
                               "index [%ld] from eCryptfs inode "
-                              "mapping; rc = [%d]\n", __FUNCTION__,
+                              "mapping; rc = [%d]\n", __func__,
                               ecryptfs_page_idx, rc);
                        goto out;
                }
                rc = ecryptfs_decrypt_page(ecryptfs_page);
                if (rc) {
                        printk(KERN_ERR "%s: Error decrypting "
-                              "page; rc = [%d]\n", __FUNCTION__, rc);
+                              "page; rc = [%d]\n", __func__, rc);
                        ClearPageUptodate(ecryptfs_page);
                        page_cache_release(ecryptfs_page);
                        goto out;
index a415f42d32cf66aba720da4e05b2a0ccfdd55663..221086fef1743545c143a270bd1bc228cfb33561 100644 (file)
@@ -257,25 +257,6 @@ static inline int ep_cmp_ffd(struct epoll_filefd *p1,
                (p1->file < p2->file ? -1 : p1->fd - p2->fd));
 }
 
-/* Special initialization for the RB tree node to detect linkage */
-static inline void ep_rb_initnode(struct rb_node *n)
-{
-       rb_set_parent(n, n);
-}
-
-/* Removes a node from the RB tree and marks it for a fast is-linked check */
-static inline void ep_rb_erase(struct rb_node *n, struct rb_root *r)
-{
-       rb_erase(n, r);
-       rb_set_parent(n, n);
-}
-
-/* Fast check to verify that the item is linked to the main RB tree */
-static inline int ep_rb_linked(struct rb_node *n)
-{
-       return rb_parent(n) != n;
-}
-
 /* Tells us if the item is currently linked */
 static inline int ep_is_linked(struct list_head *p)
 {
@@ -283,13 +264,13 @@ static inline int ep_is_linked(struct list_head *p)
 }
 
 /* Get the "struct epitem" from a wait queue pointer */
-static inline struct epitem * ep_item_from_wait(wait_queue_t *p)
+static inline struct epitem *ep_item_from_wait(wait_queue_t *p)
 {
        return container_of(p, struct eppoll_entry, wait)->base;
 }
 
 /* Get the "struct epitem" from an epoll queue wrapper */
-static inline struct epitem * ep_item_from_epqueue(poll_table *p)
+static inline struct epitem *ep_item_from_epqueue(poll_table *p)
 {
        return container_of(p, struct ep_pqueue, pt)->epi;
 }
@@ -411,8 +392,7 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
                list_del_init(&epi->fllink);
        spin_unlock(&file->f_ep_lock);
 
-       if (ep_rb_linked(&epi->rbn))
-               ep_rb_erase(&epi->rbn, &ep->rbr);
+       rb_erase(&epi->rbn, &ep->rbr);
 
        spin_lock_irqsave(&ep->lock, flags);
        if (ep_is_linked(&epi->rdllink))
@@ -728,7 +708,6 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
                goto error_return;
 
        /* Item initialization follow here ... */
-       ep_rb_initnode(&epi->rbn);
        INIT_LIST_HEAD(&epi->rdllink);
        INIT_LIST_HEAD(&epi->fllink);
        INIT_LIST_HEAD(&epi->pwqlist);
@@ -1262,7 +1241,7 @@ error_return:
        return error;
 }
 
-#ifdef TIF_RESTORE_SIGMASK
+#ifdef HAVE_SET_RESTORE_SIGMASK
 
 /*
  * Implement the event wait interface for the eventpoll file. It is the kernel
@@ -1300,7 +1279,7 @@ asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events,
                if (error == -EINTR) {
                        memcpy(&current->saved_sigmask, &sigsaved,
                               sizeof(sigsaved));
-                       set_thread_flag(TIF_RESTORE_SIGMASK);
+                       set_restore_sigmask();
                } else
                        sigprocmask(SIG_SETMASK, &sigsaved, NULL);
        }
@@ -1308,7 +1287,7 @@ asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events,
        return error;
 }
 
-#endif /* #ifdef TIF_RESTORE_SIGMASK */
+#endif /* HAVE_SET_RESTORE_SIGMASK */
 
 static int __init eventpoll_init(void)
 {
@@ -1330,4 +1309,3 @@ static int __init eventpoll_init(void)
        return 0;
 }
 fs_initcall(eventpoll_init);
-
index b152029f18f61e68e260d63bab4a9720f2e31ab6..9f9f931ef949987e29ba89204387c1428e491c66 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -735,6 +735,7 @@ static int exec_mmap(struct mm_struct *mm)
        tsk->active_mm = mm;
        activate_mm(active_mm, mm);
        task_unlock(tsk);
+       mm_update_next_owner(mm);
        arch_pick_mmap_layout(mm);
        if (old_mm) {
                up_read(&old_mm->mmap_sem);
@@ -765,9 +766,7 @@ static int de_thread(struct task_struct *tsk)
 
        /*
         * Kill all other threads in the thread group.
-        * We must hold tasklist_lock to call zap_other_threads.
         */
-       read_lock(&tasklist_lock);
        spin_lock_irq(lock);
        if (signal_group_exit(sig)) {
                /*
@@ -775,21 +774,10 @@ static int de_thread(struct task_struct *tsk)
                 * return so that the signal is processed.
                 */
                spin_unlock_irq(lock);
-               read_unlock(&tasklist_lock);
                return -EAGAIN;
        }
-
-       /*
-        * child_reaper ignores SIGKILL, change it now.
-        * Reparenting needs write_lock on tasklist_lock,
-        * so it is safe to do it under read_lock.
-        */
-       if (unlikely(tsk->group_leader == task_child_reaper(tsk)))
-               task_active_pid_ns(tsk)->child_reaper = tsk;
-
        sig->group_exit_task = tsk;
        zap_other_threads(tsk);
-       read_unlock(&tasklist_lock);
 
        /* Account for the thread group leader hanging around: */
        count = thread_group_leader(tsk) ? 1 : 2;
@@ -810,7 +798,7 @@ static int de_thread(struct task_struct *tsk)
        if (!thread_group_leader(tsk)) {
                leader = tsk->group_leader;
 
-               sig->notify_count = -1;
+               sig->notify_count = -1; /* for exit_notify() */
                for (;;) {
                        write_lock_irq(&tasklist_lock);
                        if (likely(leader->exit_state))
@@ -820,6 +808,8 @@ static int de_thread(struct task_struct *tsk)
                        schedule();
                }
 
+               if (unlikely(task_child_reaper(tsk) == leader))
+                       task_active_pid_ns(tsk)->child_reaper = tsk;
                /*
                 * The only record we have of the real-time age of a
                 * process, regardless of execs it's done, is start_time.
@@ -963,6 +953,8 @@ int flush_old_exec(struct linux_binprm * bprm)
        if (retval)
                goto out;
 
+       set_mm_exe_file(bprm->mm, bprm->file);
+
        /*
         * Release all of the old mmap stuff
         */
@@ -1268,7 +1260,6 @@ int do_execve(char * filename,
 {
        struct linux_binprm *bprm;
        struct file *file;
-       unsigned long env_p;
        struct files_struct *displaced;
        int retval;
 
@@ -1321,11 +1312,9 @@ int do_execve(char * filename,
        if (retval < 0)
                goto out;
 
-       env_p = bprm->p;
        retval = copy_strings(bprm->argc, argv, bprm);
        if (retval < 0)
                goto out;
-       bprm->argv_len = env_p - bprm->p;
 
        retval = search_binary_handler(bprm,regs);
        if (retval >= 0) {
index 109ab5e44eca3f6d5961f721b582d137779c6265..cc91227d3bb88dcdce06b83806baf6dd7f912225 100644 (file)
@@ -150,12 +150,12 @@ reconnect_path(struct vfsmount *mnt, struct dentry *target_dir)
                        if (IS_ERR(ppd)) {
                                err = PTR_ERR(ppd);
                                dprintk("%s: get_parent of %ld failed, err %d\n",
-                                       __FUNCTION__, pd->d_inode->i_ino, err);
+                                       __func__, pd->d_inode->i_ino, err);
                                dput(pd);
                                break;
                        }
 
-                       dprintk("%s: find name of %lu in %lu\n", __FUNCTION__,
+                       dprintk("%s: find name of %lu in %lu\n", __func__,
                                pd->d_inode->i_ino, ppd->d_inode->i_ino);
                        err = exportfs_get_name(mnt, ppd, nbuf, pd);
                        if (err) {
@@ -168,14 +168,14 @@ reconnect_path(struct vfsmount *mnt, struct dentry *target_dir)
                                        continue;
                                break;
                        }
-                       dprintk("%s: found name: %s\n", __FUNCTION__, nbuf);
+                       dprintk("%s: found name: %s\n", __func__, nbuf);
                        mutex_lock(&ppd->d_inode->i_mutex);
                        npd = lookup_one_len(nbuf, ppd, strlen(nbuf));
                        mutex_unlock(&ppd->d_inode->i_mutex);
                        if (IS_ERR(npd)) {
                                err = PTR_ERR(npd);
                                dprintk("%s: lookup failed: %d\n",
-                                       __FUNCTION__, err);
+                                       __func__, err);
                                dput(ppd);
                                dput(pd);
                                break;
@@ -188,7 +188,7 @@ reconnect_path(struct vfsmount *mnt, struct dentry *target_dir)
                        if (npd == pd)
                                noprogress = 0;
                        else
-                               printk("%s: npd != pd\n", __FUNCTION__);
+                               printk("%s: npd != pd\n", __func__);
                        dput(npd);
                        dput(ppd);
                        if (IS_ROOT(pd)) {
index cc47b76091bf784063503793c7529dc860d7b57d..6ae4ecf3ce40b646da679ba6b2a1ecb6149e7e00 100644 (file)
@@ -1261,10 +1261,11 @@ static int ext3_ordered_write_end(struct file *file,
                new_i_size = pos + copied;
                if (new_i_size > EXT3_I(inode)->i_disksize)
                        EXT3_I(inode)->i_disksize = new_i_size;
-               copied = ext3_generic_write_end(file, mapping, pos, len, copied,
+               ret2 = ext3_generic_write_end(file, mapping, pos, len, copied,
                                                        page, fsdata);
-               if (copied < 0)
-                       ret = copied;
+               copied = ret2;
+               if (ret2 < 0)
+                       ret = ret2;
        }
        ret2 = ext3_journal_stop(handle);
        if (!ret)
@@ -1289,10 +1290,11 @@ static int ext3_writeback_write_end(struct file *file,
        if (new_i_size > EXT3_I(inode)->i_disksize)
                EXT3_I(inode)->i_disksize = new_i_size;
 
-       copied = ext3_generic_write_end(file, mapping, pos, len, copied,
+       ret2 = ext3_generic_write_end(file, mapping, pos, len, copied,
                                                        page, fsdata);
-       if (copied < 0)
-               ret = copied;
+       copied = ret2;
+       if (ret2 < 0)
+               ret = ret2;
 
        ret2 = ext3_journal_stop(handle);
        if (!ret)
index a8bae8cd1d5de707c9a8772464ca4ecaa93044ed..3c8dab880d91f1bb38247d44d605f2bc3943a90e 100644 (file)
@@ -9,8 +9,8 @@
 #include <linux/slab.h>
 #include <linux/capability.h>
 #include <linux/fs.h>
-#include <linux/ext4_jbd2.h>
-#include <linux/ext4_fs.h>
+#include "ext4_jbd2.h"
+#include "ext4.h"
 #include "xattr.h"
 #include "acl.h"
 
@@ -37,7 +37,7 @@ ext4_acl_from_disk(const void *value, size_t size)
                return ERR_PTR(-EINVAL);
        if (count == 0)
                return NULL;
-       acl = posix_acl_alloc(count, GFP_KERNEL);
+       acl = posix_acl_alloc(count, GFP_NOFS);
        if (!acl)
                return ERR_PTR(-ENOMEM);
        for (n=0; n < count; n++) {
@@ -91,7 +91,7 @@ ext4_acl_to_disk(const struct posix_acl *acl, size_t *size)
 
        *size = ext4_acl_size(acl->a_count);
        ext_acl = kmalloc(sizeof(ext4_acl_header) + acl->a_count *
-                       sizeof(ext4_acl_entry), GFP_KERNEL);
+                       sizeof(ext4_acl_entry), GFP_NOFS);
        if (!ext_acl)
                return ERR_PTR(-ENOMEM);
        ext_acl->a_version = cpu_to_le32(EXT4_ACL_VERSION);
@@ -187,7 +187,7 @@ ext4_get_acl(struct inode *inode, int type)
        }
        retval = ext4_xattr_get(inode, name_index, "", NULL, 0);
        if (retval > 0) {
-               value = kmalloc(retval, GFP_KERNEL);
+               value = kmalloc(retval, GFP_NOFS);
                if (!value)
                        return ERR_PTR(-ENOMEM);
                retval = ext4_xattr_get(inode, name_index, "", value, retval);
@@ -335,7 +335,7 @@ ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
                        if (error)
                                goto cleanup;
                }
-               clone = posix_acl_clone(acl, GFP_KERNEL);
+               clone = posix_acl_clone(acl, GFP_NOFS);
                error = -ENOMEM;
                if (!clone)
                        goto cleanup;
index 0737e05ba3dd22842429f287356ca1c500265943..da994374ec3b2c6e13c103bf9e83b7dd87353edc 100644 (file)
 #include <linux/capability.h>
 #include <linux/fs.h>
 #include <linux/jbd2.h>
-#include <linux/ext4_fs.h>
-#include <linux/ext4_jbd2.h>
 #include <linux/quotaops.h>
 #include <linux/buffer_head.h>
-
+#include "ext4.h"
+#include "ext4_jbd2.h"
 #include "group.h"
+
 /*
  * balloc.c contains the blocks allocation and deallocation routines
  */
@@ -48,7 +48,6 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
 unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
                 ext4_group_t block_group, struct ext4_group_desc *gdp)
 {
-       unsigned long start;
        int bit, bit_max;
        unsigned free_blocks, group_blocks;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
@@ -59,7 +58,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
                /* If checksum is bad mark all blocks used to prevent allocation
                 * essentially implementing a per-group read-only flag. */
                if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
-                       ext4_error(sb, __FUNCTION__,
+                       ext4_error(sb, __func__,
                                  "Checksum bad for group %lu\n", block_group);
                        gdp->bg_free_blocks_count = 0;
                        gdp->bg_free_inodes_count = 0;
@@ -106,11 +105,12 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
        free_blocks = group_blocks - bit_max;
 
        if (bh) {
+               ext4_fsblk_t start;
+
                for (bit = 0; bit < bit_max; bit++)
                        ext4_set_bit(bit, bh->b_data);
 
-               start = block_group * EXT4_BLOCKS_PER_GROUP(sb) +
-                       le32_to_cpu(sbi->s_es->s_first_data_block);
+               start = ext4_group_first_block_no(sb, block_group);
 
                /* Set bits for block and inode bitmaps, and inode table */
                ext4_set_bit(ext4_block_bitmap(sb, gdp) - start, bh->b_data);
@@ -235,7 +235,7 @@ static int ext4_valid_block_bitmap(struct super_block *sb,
                return 1;
 
 err_out:
-       ext4_error(sb, __FUNCTION__,
+       ext4_error(sb, __func__,
                        "Invalid block bitmap - "
                        "block_group = %d, block = %llu",
                        block_group, bitmap_blk);
@@ -264,7 +264,7 @@ read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
        bitmap_blk = ext4_block_bitmap(sb, desc);
        bh = sb_getblk(sb, bitmap_blk);
        if (unlikely(!bh)) {
-               ext4_error(sb, __FUNCTION__,
+               ext4_error(sb, __func__,
                            "Cannot read block bitmap - "
                            "block_group = %d, block_bitmap = %llu",
                            (int)block_group, (unsigned long long)bitmap_blk);
@@ -281,7 +281,7 @@ read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
        }
        if (bh_submit_read(bh) < 0) {
                put_bh(bh);
-               ext4_error(sb, __FUNCTION__,
+               ext4_error(sb, __func__,
                            "Cannot read block bitmap - "
                            "block_group = %d, block_bitmap = %llu",
                            (int)block_group, (unsigned long long)bitmap_blk);
@@ -360,7 +360,7 @@ restart:
                BUG();
 }
 #define rsv_window_dump(root, verbose) \
-       __rsv_window_dump((root), (verbose), __FUNCTION__)
+       __rsv_window_dump((root), (verbose), __func__)
 #else
 #define rsv_window_dump(root, verbose) do {} while (0)
 #endif
@@ -740,7 +740,7 @@ do_more:
                if (!ext4_clear_bit_atomic(sb_bgl_lock(sbi, block_group),
                                                bit + i, bitmap_bh->b_data)) {
                        jbd_unlock_bh_state(bitmap_bh);
-                       ext4_error(sb, __FUNCTION__,
+                       ext4_error(sb, __func__,
                                   "bit already cleared for block %llu",
                                   (ext4_fsblk_t)(block + i));
                        jbd_lock_bh_state(bitmap_bh);
@@ -752,9 +752,7 @@ do_more:
        jbd_unlock_bh_state(bitmap_bh);
 
        spin_lock(sb_bgl_lock(sbi, block_group));
-       desc->bg_free_blocks_count =
-               cpu_to_le16(le16_to_cpu(desc->bg_free_blocks_count) +
-                       group_freed);
+       le16_add_cpu(&desc->bg_free_blocks_count, group_freed);
        desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc);
        spin_unlock(sb_bgl_lock(sbi, block_group));
        percpu_counter_add(&sbi->s_freeblocks_counter, count);
@@ -1798,7 +1796,7 @@ allocated:
                        if (ext4_test_bit(grp_alloc_blk+i,
                                        bh2jh(bitmap_bh)->b_committed_data)) {
                                printk("%s: block was unexpectedly set in "
-                                       "b_committed_data\n", __FUNCTION__);
+                                       "b_committed_data\n", __func__);
                        }
                }
        }
@@ -1823,8 +1821,7 @@ allocated:
        spin_lock(sb_bgl_lock(sbi, group_no));
        if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))
                gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
-       gdp->bg_free_blocks_count =
-                       cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)-num);
+       le16_add_cpu(&gdp->bg_free_blocks_count, -num);
        gdp->bg_checksum = ext4_group_desc_csum(sbi, group_no, gdp);
        spin_unlock(sb_bgl_lock(sbi, group_no));
        percpu_counter_sub(&sbi->s_freeblocks_counter, num);
index 420554f8f79d8f4fb4a99a95bec9539e6c78f8bc..d37ea67504549c8d5c36958194323b50e2dd6ce7 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <linux/buffer_head.h>
 #include <linux/jbd2.h>
-#include <linux/ext4_fs.h>
+#include "ext4.h"
 
 #ifdef EXT4FS_DEBUG
 
index 2c23bade9aa676451972905449e8d8cc0bbcfec3..2bf0331ea1946303f0caedf360dce0cb9dc38445 100644 (file)
 
 #include <linux/fs.h>
 #include <linux/jbd2.h>
-#include <linux/ext4_fs.h>
 #include <linux/buffer_head.h>
 #include <linux/slab.h>
 #include <linux/rbtree.h>
+#include "ext4.h"
 
 static unsigned char ext4_filetype_table[] = {
        DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
@@ -42,7 +42,7 @@ const struct file_operations ext4_dir_operations = {
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
        .readdir        = ext4_readdir,         /* we take BKL. needed?*/
-       .ioctl          = ext4_ioctl,           /* BKL held */
+       .unlocked_ioctl = ext4_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = ext4_compat_ioctl,
 #endif
similarity index 99%
rename from include/linux/ext4_fs.h
rename to fs/ext4/ext4.h
index 25003254859773c657f510d0e2460c900d47a6c9..8158083f7ac0a04673529125fe2aa58babd4cb8d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/include/linux/ext4_fs.h
+ *  ext4.h
  *
  * Copyright (C) 1992, 1993, 1994, 1995
  * Remy Card (card@masi.ibp.fr)
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#ifndef _LINUX_EXT4_FS_H
-#define _LINUX_EXT4_FS_H
+#ifndef _EXT4_H
+#define _EXT4_H
 
 #include <linux/types.h>
 #include <linux/blkdev.h>
 #include <linux/magic.h>
-
-#include <linux/ext4_fs_i.h>
+#include "ext4_i.h"
 
 /*
  * The second extended filesystem constants/structures
@@ -176,8 +175,7 @@ struct ext4_group_desc
 #define EXT4_BG_INODE_ZEROED   0x0004 /* On-disk itable initialized to zero */
 
 #ifdef __KERNEL__
-#include <linux/ext4_fs_i.h>
-#include <linux/ext4_fs_sb.h>
+#include "ext4_sb.h"
 #endif
 /*
  * Macro-instructions used to manage group descriptors
@@ -231,6 +229,7 @@ struct ext4_group_desc
 #define EXT4_TOPDIR_FL                 0x00020000 /* Top of directory hierarchies*/
 #define EXT4_HUGE_FILE_FL               0x00040000 /* Set to each huge file */
 #define EXT4_EXTENTS_FL                        0x00080000 /* Inode uses extents */
+#define EXT4_EXT_MIGRATE               0x00100000 /* Inode is migrating */
 #define EXT4_RESERVED_FL               0x80000000 /* reserved for ext4 lib */
 
 #define EXT4_FL_USER_VISIBLE           0x000BDFFF /* User visible flags */
@@ -1049,8 +1048,7 @@ extern int ext4_block_truncate_page(handle_t *handle, struct page *page,
                struct address_space *mapping, loff_t from);
 
 /* ioctl.c */
-extern int ext4_ioctl (struct inode *, struct file *, unsigned int,
-                      unsigned long);
+extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
 extern long ext4_compat_ioctl (struct file *, unsigned int, unsigned long);
 
 /* migrate.c */
@@ -1204,4 +1202,4 @@ extern int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode,
                        int extend_disksize);
 #endif /* __KERNEL__ */
 
-#endif /* _LINUX_EXT4_FS_H */
+#endif /* _EXT4_H */
similarity index 98%
rename from include/linux/ext4_fs_extents.h
rename to fs/ext4/ext4_extents.h
index 1285c583b2d868421366fc71bb05cc12c507225f..75333b595fab794bda6023a3978b0c61df5e91de 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
  */
 
-#ifndef _LINUX_EXT4_EXTENTS
-#define _LINUX_EXT4_EXTENTS
+#ifndef _EXT4_EXTENTS
+#define _EXT4_EXTENTS
 
-#include <linux/ext4_fs.h>
+#include "ext4.h"
 
 /*
  * With AGGRESSIVE_TEST defined, the capacity of index/leaf blocks
@@ -228,5 +228,5 @@ extern int ext4_ext_search_left(struct inode *, struct ext4_ext_path *,
 extern int ext4_ext_search_right(struct inode *, struct ext4_ext_path *,
                                                ext4_lblk_t *, ext4_fsblk_t *);
 extern void ext4_ext_drop_refs(struct ext4_ext_path *);
-#endif /* _LINUX_EXT4_EXTENTS */
+#endif /* _EXT4_EXTENTS */
 
similarity index 97%
rename from include/linux/ext4_fs_i.h
rename to fs/ext4/ext4_i.h
index d5508d3cf29096db958efa7be8719d69fb155ac0..26a4ae255d79da02ad615de4bf6217f1dc5287b0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/include/linux/ext4_fs_i.h
+ *  ext4_i.h
  *
  * Copyright (C) 1992, 1993, 1994, 1995
  * Remy Card (card@masi.ibp.fr)
@@ -13,8 +13,8 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#ifndef _LINUX_EXT4_FS_I
-#define _LINUX_EXT4_FS_I
+#ifndef _EXT4_I
+#define _EXT4_I
 
 #include <linux/rwsem.h>
 #include <linux/rbtree.h>
@@ -164,4 +164,4 @@ struct ext4_inode_info {
        spinlock_t i_prealloc_lock;
 };
 
-#endif /* _LINUX_EXT4_FS_I */
+#endif /* _EXT4_I */
index d6afe4e273403147c091cdc7d3807b90d6f6083e..c75384b34f2c7e1f587818cafc301a5d6aae5b1e 100644 (file)
@@ -2,14 +2,14 @@
  * Interface between ext4 and JBD
  */
 
-#include <linux/ext4_jbd2.h>
+#include "ext4_jbd2.h"
 
 int __ext4_journal_get_undo_access(const char *where, handle_t *handle,
                                struct buffer_head *bh)
 {
        int err = jbd2_journal_get_undo_access(handle, bh);
        if (err)
-               ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+               ext4_journal_abort_handle(where, __func__, bh, handle, err);
        return err;
 }
 
@@ -18,7 +18,7 @@ int __ext4_journal_get_write_access(const char *where, handle_t *handle,
 {
        int err = jbd2_journal_get_write_access(handle, bh);
        if (err)
-               ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+               ext4_journal_abort_handle(where, __func__, bh, handle, err);
        return err;
 }
 
@@ -27,7 +27,7 @@ int __ext4_journal_forget(const char *where, handle_t *handle,
 {
        int err = jbd2_journal_forget(handle, bh);
        if (err)
-               ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+               ext4_journal_abort_handle(where, __func__, bh, handle, err);
        return err;
 }
 
@@ -36,7 +36,7 @@ int __ext4_journal_revoke(const char *where, handle_t *handle,
 {
        int err = jbd2_journal_revoke(handle, blocknr, bh);
        if (err)
-               ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+               ext4_journal_abort_handle(where, __func__, bh, handle, err);
        return err;
 }
 
@@ -45,7 +45,7 @@ int __ext4_journal_get_create_access(const char *where,
 {
        int err = jbd2_journal_get_create_access(handle, bh);
        if (err)
-               ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+               ext4_journal_abort_handle(where, __func__, bh, handle, err);
        return err;
 }
 
@@ -54,6 +54,6 @@ int __ext4_journal_dirty_metadata(const char *where,
 {
        int err = jbd2_journal_dirty_metadata(handle, bh);
        if (err)
-               ext4_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
+               ext4_journal_abort_handle(where, __func__, bh, handle, err);
        return err;
 }
similarity index 98%
rename from include/linux/ext4_jbd2.h
rename to fs/ext4/ext4_jbd2.h
index 38c71d3c8dbf39efff5278fa9c58272d70c4554b..9255a7d28b245546d16001359129aaad43883113 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/include/linux/ext4_jbd2.h
+ * ext4_jbd2.h
  *
  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
  *
  * Ext4-specific journaling extensions.
  */
 
-#ifndef _LINUX_EXT4_JBD2_H
-#define _LINUX_EXT4_JBD2_H
+#ifndef _EXT4_JBD2_H
+#define _EXT4_JBD2_H
 
 #include <linux/fs.h>
 #include <linux/jbd2.h>
-#include <linux/ext4_fs.h>
+#include "ext4.h"
 
 #define EXT4_JOURNAL(inode)    (EXT4_SB((inode)->i_sb)->s_journal)
 
@@ -228,4 +228,4 @@ static inline int ext4_should_writeback_data(struct inode *inode)
        return 0;
 }
 
-#endif /* _LINUX_EXT4_JBD2_H */
+#endif /* _EXT4_JBD2_H */
similarity index 97%
rename from include/linux/ext4_fs_sb.h
rename to fs/ext4/ext4_sb.h
index abaae2c8cccf3d7bad74769998816f0b081e7d5d..5802e69f2191d015286924887538264a0b3b2325 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/include/linux/ext4_fs_sb.h
+ *  ext4_sb.h
  *
  * Copyright (C) 1992, 1993, 1994, 1995
  * Remy Card (card@masi.ibp.fr)
@@ -13,8 +13,8 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#ifndef _LINUX_EXT4_FS_SB
-#define _LINUX_EXT4_FS_SB
+#ifndef _EXT4_SB
+#define _EXT4_SB
 
 #ifdef __KERNEL__
 #include <linux/timer.h>
@@ -145,4 +145,4 @@ struct ext4_sb_info {
        struct ext4_locality_group *s_locality_groups;
 };
 
-#endif /* _LINUX_EXT4_FS_SB */
+#endif /* _EXT4_SB */
index 9ae6e67090cdfad1bd52a7e7169ba725dea19c82..47929c4e3dae66d104f5bdd6ac39f5436183dff5 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/time.h>
-#include <linux/ext4_jbd2.h>
 #include <linux/jbd2.h>
 #include <linux/highuid.h>
 #include <linux/pagemap.h>
@@ -40,8 +39,9 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/falloc.h>
-#include <linux/ext4_fs_extents.h>
 #include <asm/uaccess.h>
+#include "ext4_jbd2.h"
+#include "ext4_extents.h"
 
 
 /*
@@ -308,7 +308,7 @@ corrupted:
 }
 
 #define ext4_ext_check_header(inode, eh, depth)        \
-       __ext4_ext_check_header(__FUNCTION__, inode, eh, depth)
+       __ext4_ext_check_header(__func__, inode, eh, depth)
 
 #ifdef EXT_DEBUG
 static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path)
@@ -614,7 +614,7 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
 
        ix->ei_block = cpu_to_le32(logical);
        ext4_idx_store_pblock(ix, ptr);
-       curp->p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(curp->p_hdr->eh_entries)+1);
+       le16_add_cpu(&curp->p_hdr->eh_entries, 1);
 
        BUG_ON(le16_to_cpu(curp->p_hdr->eh_entries)
                             > le16_to_cpu(curp->p_hdr->eh_max));
@@ -736,7 +736,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
        }
        if (m) {
                memmove(ex, path[depth].p_ext-m, sizeof(struct ext4_extent)*m);
-               neh->eh_entries = cpu_to_le16(le16_to_cpu(neh->eh_entries)+m);
+               le16_add_cpu(&neh->eh_entries, m);
        }
 
        set_buffer_uptodate(bh);
@@ -753,8 +753,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
                err = ext4_ext_get_access(handle, inode, path + depth);
                if (err)
                        goto cleanup;
-               path[depth].p_hdr->eh_entries =
-                    cpu_to_le16(le16_to_cpu(path[depth].p_hdr->eh_entries)-m);
+               le16_add_cpu(&path[depth].p_hdr->eh_entries, -m);
                err = ext4_ext_dirty(handle, inode, path + depth);
                if (err)
                        goto cleanup;
@@ -817,8 +816,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
                if (m) {
                        memmove(++fidx, path[i].p_idx - m,
                                sizeof(struct ext4_extent_idx) * m);
-                       neh->eh_entries =
-                               cpu_to_le16(le16_to_cpu(neh->eh_entries) + m);
+                       le16_add_cpu(&neh->eh_entries, m);
                }
                set_buffer_uptodate(bh);
                unlock_buffer(bh);
@@ -834,7 +832,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
                        err = ext4_ext_get_access(handle, inode, path + i);
                        if (err)
                                goto cleanup;
-                       path[i].p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(path[i].p_hdr->eh_entries)-m);
+                       le16_add_cpu(&path[i].p_hdr->eh_entries, -m);
                        err = ext4_ext_dirty(handle, inode, path + i);
                        if (err)
                                goto cleanup;
@@ -1369,7 +1367,7 @@ int ext4_ext_try_to_merge(struct inode *inode,
                                * sizeof(struct ext4_extent);
                        memmove(ex + 1, ex + 2, len);
                }
-               eh->eh_entries = cpu_to_le16(le16_to_cpu(eh->eh_entries) - 1);
+               le16_add_cpu(&eh->eh_entries, -1);
                merge_done = 1;
                WARN_ON(eh->eh_entries == 0);
                if (!eh->eh_entries)
@@ -1560,7 +1558,7 @@ has_space:
                path[depth].p_ext = nearex;
        }
 
-       eh->eh_entries = cpu_to_le16(le16_to_cpu(eh->eh_entries)+1);
+       le16_add_cpu(&eh->eh_entries, 1);
        nearex = path[depth].p_ext;
        nearex->ee_block = newext->ee_block;
        ext4_ext_store_pblock(nearex, ext_pblock(newext));
@@ -1699,7 +1697,7 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode,
        err = ext4_ext_get_access(handle, inode, path);
        if (err)
                return err;
-       path->p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(path->p_hdr->eh_entries)-1);
+       le16_add_cpu(&path->p_hdr->eh_entries, -1);
        err = ext4_ext_dirty(handle, inode, path);
        if (err)
                return err;
@@ -1902,7 +1900,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
                if (num == 0) {
                        /* this extent is removed; mark slot entirely unused */
                        ext4_ext_store_pblock(ex, 0);
-                       eh->eh_entries = cpu_to_le16(le16_to_cpu(eh->eh_entries)-1);
+                       le16_add_cpu(&eh->eh_entries, -1);
                }
 
                ex->ee_block = cpu_to_le32(block);
@@ -1979,7 +1977,7 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start)
         * We start scanning from right side, freeing all the blocks
         * after i_size and walking into the tree depth-wise.
         */
-       path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1), GFP_KERNEL);
+       path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1), GFP_NOFS);
        if (path == NULL) {
                ext4_journal_stop(handle);
                return -ENOMEM;
@@ -2138,6 +2136,82 @@ void ext4_ext_release(struct super_block *sb)
 #endif
 }
 
+static void bi_complete(struct bio *bio, int error)
+{
+       complete((struct completion *)bio->bi_private);
+}
+
+/* FIXME!! we need to try to merge to left or right after zero-out  */
+static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex)
+{
+       int ret = -EIO;
+       struct bio *bio;
+       int blkbits, blocksize;
+       sector_t ee_pblock;
+       struct completion event;
+       unsigned int ee_len, len, done, offset;
+
+
+       blkbits   = inode->i_blkbits;
+       blocksize = inode->i_sb->s_blocksize;
+       ee_len    = ext4_ext_get_actual_len(ex);
+       ee_pblock = ext_pblock(ex);
+
+       /* convert ee_pblock to 512 byte sectors */
+       ee_pblock = ee_pblock << (blkbits - 9);
+
+       while (ee_len > 0) {
+
+               if (ee_len > BIO_MAX_PAGES)
+                       len = BIO_MAX_PAGES;
+               else
+                       len = ee_len;
+
+               bio = bio_alloc(GFP_NOIO, len);
+               if (!bio)
+                       return -ENOMEM;
+               bio->bi_sector = ee_pblock;
+               bio->bi_bdev   = inode->i_sb->s_bdev;
+
+               done = 0;
+               offset = 0;
+               while (done < len) {
+                       ret = bio_add_page(bio, ZERO_PAGE(0),
+                                                       blocksize, offset);
+                       if (ret != blocksize) {
+                               /*
+                                * We can't add any more pages because of
+                                * hardware limitations.  Start a new bio.
+                                */
+                               break;
+                       }
+                       done++;
+                       offset += blocksize;
+                       if (offset >= PAGE_CACHE_SIZE)
+                               offset = 0;
+               }
+
+               init_completion(&event);
+               bio->bi_private = &event;
+               bio->bi_end_io = bi_complete;
+               submit_bio(WRITE, bio);
+               wait_for_completion(&event);
+
+               if (test_bit(BIO_UPTODATE, &bio->bi_flags))
+                       ret = 0;
+               else {
+                       ret = -EIO;
+                       break;
+               }
+               bio_put(bio);
+               ee_len    -= done;
+               ee_pblock += done  << (blkbits - 9);
+       }
+       return ret;
+}
+
+#define EXT4_EXT_ZERO_LEN 7
+
 /*
  * This function is called by ext4_ext_get_blocks() if someone tries to write
  * to an uninitialized extent. It may result in splitting the uninitialized
@@ -2154,7 +2228,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
                                                ext4_lblk_t iblock,
                                                unsigned long max_blocks)
 {
-       struct ext4_extent *ex, newex;
+       struct ext4_extent *ex, newex, orig_ex;
        struct ext4_extent *ex1 = NULL;
        struct ext4_extent *ex2 = NULL;
        struct ext4_extent *ex3 = NULL;
@@ -2173,10 +2247,26 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
        allocated = ee_len - (iblock - ee_block);
        newblock = iblock - ee_block + ext_pblock(ex);
        ex2 = ex;
+       orig_ex.ee_block = ex->ee_block;
+       orig_ex.ee_len   = cpu_to_le16(ee_len);
+       ext4_ext_store_pblock(&orig_ex, ext_pblock(ex));
 
        err = ext4_ext_get_access(handle, inode, path + depth);
        if (err)
                goto out;
+       /* If extent has less than 2*EXT4_EXT_ZERO_LEN zerout directly */
+       if (ee_len <= 2*EXT4_EXT_ZERO_LEN) {
+               err =  ext4_ext_zeroout(inode, &orig_ex);
+               if (err)
+                       goto fix_extent_len;
+               /* update the extent length and mark as initialized */
+               ex->ee_block = orig_ex.ee_block;
+               ex->ee_len   = orig_ex.ee_len;
+               ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
+               ext4_ext_dirty(handle, inode, path + depth);
+               /* zeroed the full extent */
+               return allocated;
+       }
 
        /* ex1: ee_block to iblock - 1 : uninitialized */
        if (iblock > ee_block) {
@@ -2195,19 +2285,103 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
        /* ex3: to ee_block + ee_len : uninitialised */
        if (allocated > max_blocks) {
                unsigned int newdepth;
+               /* If extent has less than EXT4_EXT_ZERO_LEN zerout directly */
+               if (allocated <= EXT4_EXT_ZERO_LEN) {
+                       /* Mark first half uninitialized.
+                        * Mark second half initialized and zero out the
+                        * initialized extent
+                        */
+                       ex->ee_block = orig_ex.ee_block;
+                       ex->ee_len   = cpu_to_le16(ee_len - allocated);
+                       ext4_ext_mark_uninitialized(ex);
+                       ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
+                       ext4_ext_dirty(handle, inode, path + depth);
+
+                       ex3 = &newex;
+                       ex3->ee_block = cpu_to_le32(iblock);
+                       ext4_ext_store_pblock(ex3, newblock);
+                       ex3->ee_len = cpu_to_le16(allocated);
+                       err = ext4_ext_insert_extent(handle, inode, path, ex3);
+                       if (err == -ENOSPC) {
+                               err =  ext4_ext_zeroout(inode, &orig_ex);
+                               if (err)
+                                       goto fix_extent_len;
+                               ex->ee_block = orig_ex.ee_block;
+                               ex->ee_len   = orig_ex.ee_len;
+                               ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
+                               ext4_ext_dirty(handle, inode, path + depth);
+                               /* zeroed the full extent */
+                               return allocated;
+
+                       } else if (err)
+                               goto fix_extent_len;
+
+                       /*
+                        * We need to zero out the second half because
+                        * an fallocate request can update file size and
+                        * converting the second half to initialized extent
+                        * implies that we can leak some junk data to user
+                        * space.
+                        */
+                       err =  ext4_ext_zeroout(inode, ex3);
+                       if (err) {
+                               /*
+                                * We should actually mark the
+                                * second half as uninit and return error
+                                * Insert would have changed the extent
+                                */
+                               depth = ext_depth(inode);
+                               ext4_ext_drop_refs(path);
+                               path = ext4_ext_find_extent(inode,
+                                                               iblock, path);
+                               if (IS_ERR(path)) {
+                                       err = PTR_ERR(path);
+                                       return err;
+                               }
+                               ex = path[depth].p_ext;
+                               err = ext4_ext_get_access(handle, inode,
+                                                               path + depth);
+                               if (err)
+                                       return err;
+                               ext4_ext_mark_uninitialized(ex);
+                               ext4_ext_dirty(handle, inode, path + depth);
+                               return err;
+                       }
+
+                       /* zeroed the second half */
+                       return allocated;
+               }
                ex3 = &newex;
                ex3->ee_block = cpu_to_le32(iblock + max_blocks);
                ext4_ext_store_pblock(ex3, newblock + max_blocks);
                ex3->ee_len = cpu_to_le16(allocated - max_blocks);
                ext4_ext_mark_uninitialized(ex3);
                err = ext4_ext_insert_extent(handle, inode, path, ex3);
-               if (err)
-                       goto out;
+               if (err == -ENOSPC) {
+                       err =  ext4_ext_zeroout(inode, &orig_ex);
+                       if (err)
+                               goto fix_extent_len;
+                       /* update the extent length and mark as initialized */
+                       ex->ee_block = orig_ex.ee_block;
+                       ex->ee_len   = orig_ex.ee_len;
+                       ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
+                       ext4_ext_dirty(handle, inode, path + depth);
+                       /* zeroed the full extent */
+                       return allocated;
+
+               } else if (err)
+                       goto fix_extent_len;
                /*
                 * The depth, and hence eh & ex might change
                 * as part of the insert above.
                 */
                newdepth = ext_depth(inode);
+               /*
+                * update the extent length after successfull insert of the
+                * split extent
+                */
+               orig_ex.ee_len = cpu_to_le16(ee_len -
+                                               ext4_ext_get_actual_len(ex3));
                if (newdepth != depth) {
                        depth = newdepth;
                        ext4_ext_drop_refs(path);
@@ -2226,6 +2400,24 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
                                goto out;
                }
                allocated = max_blocks;
+
+               /* If extent has less than EXT4_EXT_ZERO_LEN and we are trying
+                * to insert a extent in the middle zerout directly
+                * otherwise give the extent a chance to merge to left
+                */
+               if (le16_to_cpu(orig_ex.ee_len) <= EXT4_EXT_ZERO_LEN &&
+                                                       iblock != ee_block) {
+                       err =  ext4_ext_zeroout(inode, &orig_ex);
+                       if (err)
+                               goto fix_extent_len;
+                       /* update the extent length and mark as initialized */
+                       ex->ee_block = orig_ex.ee_block;
+                       ex->ee_len   = orig_ex.ee_len;
+                       ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
+                       ext4_ext_dirty(handle, inode, path + depth);
+                       /* zero out the first half */
+                       return allocated;
+               }
        }
        /*
         * If there was a change of depth as part of the
@@ -2282,8 +2474,29 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
        goto out;
 insert:
        err = ext4_ext_insert_extent(handle, inode, path, &newex);
+       if (err == -ENOSPC) {
+               err =  ext4_ext_zeroout(inode, &orig_ex);
+               if (err)
+                       goto fix_extent_len;
+               /* update the extent length and mark as initialized */
+               ex->ee_block = orig_ex.ee_block;
+               ex->ee_len   = orig_ex.ee_len;
+               ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
+               ext4_ext_dirty(handle, inode, path + depth);
+               /* zero out the first half */
+               return allocated;
+       } else if (err)
+               goto fix_extent_len;
 out:
        return err ? err : allocated;
+
+fix_extent_len:
+       ex->ee_block = orig_ex.ee_block;
+       ex->ee_len   = orig_ex.ee_len;
+       ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
+       ext4_ext_mark_uninitialized(ex);
+       ext4_ext_dirty(handle, inode, path + depth);
+       return err;
 }
 
 /*
@@ -2393,8 +2606,20 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
                        }
                        if (create == EXT4_CREATE_UNINITIALIZED_EXT)
                                goto out;
-                       if (!create)
+                       if (!create) {
+                               /*
+                                * We have blocks reserved already.  We
+                                * return allocated blocks so that delalloc
+                                * won't do block reservation for us.  But
+                                * the buffer head will be unmapped so that
+                                * a read from the block returns 0s.
+                                */
+                               if (allocated > max_blocks)
+                                       allocated = max_blocks;
+                               /* mark the buffer unwritten */
+                               __set_bit(BH_Unwritten, &bh_result->b_state);
                                goto out2;
+                       }
 
                        ret = ext4_ext_convert_to_initialized(handle, inode,
                                                                path, iblock,
@@ -2584,6 +2809,8 @@ out_stop:
                ext4_orphan_del(handle, inode);
 
        up_write(&EXT4_I(inode)->i_data_sem);
+       inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
+       ext4_mark_inode_dirty(handle, inode);
        ext4_journal_stop(handle);
 }
 
@@ -2608,6 +2835,28 @@ int ext4_ext_writepage_trans_blocks(struct inode *inode, int num)
        return needed;
 }
 
+static void ext4_falloc_update_inode(struct inode *inode,
+                               int mode, loff_t new_size, int update_ctime)
+{
+       struct timespec now;
+
+       if (update_ctime) {
+               now = current_fs_time(inode->i_sb);
+               if (!timespec_equal(&inode->i_ctime, &now))
+                       inode->i_ctime = now;
+       }
+       /*
+        * Update only when preallocation was requested beyond
+        * the file size.
+        */
+       if (!(mode & FALLOC_FL_KEEP_SIZE) &&
+                               new_size > i_size_read(inode)) {
+               i_size_write(inode, new_size);
+               EXT4_I(inode)->i_disksize = new_size;
+       }
+
+}
+
 /*
  * preallocate space for a file. This implements ext4's fallocate inode
  * operation, which gets called from sys_fallocate system call.
@@ -2619,8 +2868,8 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
 {
        handle_t *handle;
        ext4_lblk_t block;
+       loff_t new_size;
        unsigned long max_blocks;
-       ext4_fsblk_t nblocks = 0;
        int ret = 0;
        int ret2 = 0;
        int retries = 0;
@@ -2639,9 +2888,12 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
                return -ENODEV;
 
        block = offset >> blkbits;
+       /*
+        * We can't just convert len to max_blocks because
+        * If blocksize = 4096 offset = 3072 and len = 2048
+        */
        max_blocks = (EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits)
-                       - block;
-
+                                                       - block;
        /*
         * credits to insert 1 extent into extent tree + buffers to be able to
         * modify 1 super block, 1 block bitmap and 1 group descriptor.
@@ -2657,7 +2909,6 @@ retry:
                        ret = PTR_ERR(handle);
                        break;
                }
-
                ret = ext4_get_blocks_wrap(handle, inode, block,
                                          max_blocks, &map_bh,
                                          EXT4_CREATE_UNINITIALIZED_EXT, 0);
@@ -2673,61 +2924,24 @@ retry:
                        ret2 = ext4_journal_stop(handle);
                        break;
                }
-               if (ret > 0) {
-                       /* check wrap through sign-bit/zero here */
-                       if ((block + ret) < 0 || (block + ret) < block) {
-                               ret = -EIO;
-                               ext4_mark_inode_dirty(handle, inode);
-                               ret2 = ext4_journal_stop(handle);
-                               break;
-                       }
-                       if (buffer_new(&map_bh) && ((block + ret) >
-                           (EXT4_BLOCK_ALIGN(i_size_read(inode), blkbits)
-                           >> blkbits)))
-                                       nblocks = nblocks + ret;
-               }
-
-               /* Update ctime if new blocks get allocated */
-               if (nblocks) {
-                       struct timespec now;
-
-                       now = current_fs_time(inode->i_sb);
-                       if (!timespec_equal(&inode->i_ctime, &now))
-                               inode->i_ctime = now;
-               }
+               if ((block + ret) >= (EXT4_BLOCK_ALIGN(offset + len,
+                                               blkbits) >> blkbits))
+                       new_size = offset + len;
+               else
+                       new_size = (block + ret) << blkbits;
 
+               ext4_falloc_update_inode(inode, mode, new_size,
+                                               buffer_new(&map_bh));
                ext4_mark_inode_dirty(handle, inode);
                ret2 = ext4_journal_stop(handle);
                if (ret2)
                        break;
        }
-
-       if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
+       if (ret == -ENOSPC &&
+                       ext4_should_retry_alloc(inode->i_sb, &retries)) {
+               ret = 0;
                goto retry;
-
-       /*
-        * Time to update the file size.
-        * Update only when preallocation was requested beyond the file size.
-        */
-       if (!(mode & FALLOC_FL_KEEP_SIZE) &&
-           (offset + len) > i_size_read(inode)) {
-               if (ret > 0) {
-                       /*
-                        * if no error, we assume preallocation succeeded
-                        * completely
-                        */
-                       i_size_write(inode, offset + len);
-                       EXT4_I(inode)->i_disksize = i_size_read(inode);
-               } else if (ret < 0 && nblocks) {
-                       /* Handle partial allocation scenario */
-                       loff_t newsize;
-
-                       newsize  = (nblocks << blkbits) + i_size_read(inode);
-                       i_size_write(inode, EXT4_BLOCK_ALIGN(newsize, blkbits));
-                       EXT4_I(inode)->i_disksize = i_size_read(inode);
-               }
        }
-
        mutex_unlock(&inode->i_mutex);
        return ret > 0 ? ret2 : ret;
 }
index ac35ec58db55c9e9fe4b4d3effde74274b614b25..4159be6366ab8c7fb39493827765544d818b0ecc 100644 (file)
@@ -21,8 +21,8 @@
 #include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/jbd2.h>
-#include <linux/ext4_fs.h>
-#include <linux/ext4_jbd2.h>
+#include "ext4.h"
+#include "ext4_jbd2.h"
 #include "xattr.h"
 #include "acl.h"
 
@@ -129,7 +129,7 @@ const struct file_operations ext4_file_operations = {
        .write          = do_sync_write,
        .aio_read       = generic_file_aio_read,
        .aio_write      = ext4_file_write,
-       .ioctl          = ext4_ioctl,
+       .unlocked_ioctl = ext4_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = ext4_compat_ioctl,
 #endif
index 8d50879d1c2c68f23284314ff4fc7c5afe3c0a8e..1c8ba48d4f8d6014e5708b44706640e3e29a11e9 100644 (file)
@@ -27,8 +27,8 @@
 #include <linux/sched.h>
 #include <linux/writeback.h>
 #include <linux/jbd2.h>
-#include <linux/ext4_fs.h>
-#include <linux/ext4_jbd2.h>
+#include "ext4.h"
+#include "ext4_jbd2.h"
 
 /*
  * akpm: A new design for ext4_sync_file().
@@ -72,6 +72,9 @@ int ext4_sync_file(struct file * file, struct dentry *dentry, int datasync)
                goto out;
        }
 
+       if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
+               goto out;
+
        /*
         * The VFS has written the file data.  If the inode is unaltered
         * then we need not start a commit.
index 1555024e3b36b26a56f8a7c47f191740171f9934..1d6329dbe3906551929c4c8ea61e1878edfde08d 100644 (file)
@@ -11,8 +11,8 @@
 
 #include <linux/fs.h>
 #include <linux/jbd2.h>
-#include <linux/ext4_fs.h>
 #include <linux/cryptohash.h>
+#include "ext4.h"
 
 #define DELTA 0x9E3779B9
 
index 486e46a3918de44a0534db6553058c01e7cf6ef2..c6efbab0c80187942dfcedc867d514c76badcefc 100644 (file)
@@ -15,8 +15,6 @@
 #include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/jbd2.h>
-#include <linux/ext4_fs.h>
-#include <linux/ext4_jbd2.h>
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/quotaops.h>
@@ -25,7 +23,8 @@
 #include <linux/bitops.h>
 #include <linux/blkdev.h>
 #include <asm/byteorder.h>
-
+#include "ext4.h"
+#include "ext4_jbd2.h"
 #include "xattr.h"
 #include "acl.h"
 #include "group.h"
@@ -75,7 +74,7 @@ unsigned ext4_init_inode_bitmap(struct super_block *sb, struct buffer_head *bh,
        /* If checksum is bad mark all blocks and inodes use to prevent
         * allocation, essentially implementing a per-group read-only flag. */
        if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) {
-               ext4_error(sb, __FUNCTION__, "Checksum bad for group %lu\n",
+               ext4_error(sb, __func__, "Checksum bad for group %lu\n",
                           block_group);
                gdp->bg_free_blocks_count = 0;
                gdp->bg_free_inodes_count = 0;
@@ -223,11 +222,9 @@ void ext4_free_inode (handle_t *handle, struct inode * inode)
 
                if (gdp) {
                        spin_lock(sb_bgl_lock(sbi, block_group));
-                       gdp->bg_free_inodes_count = cpu_to_le16(
-                               le16_to_cpu(gdp->bg_free_inodes_count) + 1);
+                       le16_add_cpu(&gdp->bg_free_inodes_count, 1);
                        if (is_directory)
-                               gdp->bg_used_dirs_count = cpu_to_le16(
-                                 le16_to_cpu(gdp->bg_used_dirs_count) - 1);
+                               le16_add_cpu(&gdp->bg_used_dirs_count, -1);
                        gdp->bg_checksum = ext4_group_desc_csum(sbi,
                                                        block_group, gdp);
                        spin_unlock(sb_bgl_lock(sbi, block_group));
@@ -588,7 +585,7 @@ got:
        ino++;
        if ((group == 0 && ino < EXT4_FIRST_INO(sb)) ||
            ino > EXT4_INODES_PER_GROUP(sb)) {
-               ext4_error(sb, __FUNCTION__,
+               ext4_error(sb, __func__,
                           "reserved inode or inode > inodes count - "
                           "block_group = %lu, inode=%lu", group,
                           ino + group * EXT4_INODES_PER_GROUP(sb));
@@ -664,11 +661,9 @@ got:
                                cpu_to_le16(EXT4_INODES_PER_GROUP(sb) - ino);
        }
 
-       gdp->bg_free_inodes_count =
-               cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1);
+       le16_add_cpu(&gdp->bg_free_inodes_count, -1);
        if (S_ISDIR(mode)) {
-               gdp->bg_used_dirs_count =
-                       cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1);
+               le16_add_cpu(&gdp->bg_used_dirs_count, 1);
        }
        gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp);
        spin_unlock(sb_bgl_lock(sbi, group));
@@ -744,23 +739,24 @@ got:
        if (err)
                goto fail_free_drop;
 
-       err = ext4_mark_inode_dirty(handle, inode);
-       if (err) {
-               ext4_std_error(sb, err);
-               goto fail_free_drop;
-       }
        if (test_opt(sb, EXTENTS)) {
-               /* set extent flag only for directory and file */
-               if (S_ISDIR(mode) || S_ISREG(mode)) {
+               /* set extent flag only for diretory, file and normal symlink*/
+               if (S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode)) {
                        EXT4_I(inode)->i_flags |= EXT4_EXTENTS_FL;
                        ext4_ext_tree_init(handle, inode);
                        err = ext4_update_incompat_feature(handle, sb,
                                        EXT4_FEATURE_INCOMPAT_EXTENTS);
                        if (err)
-                               goto fail;
+                               goto fail_free_drop;
                }
        }
 
+       err = ext4_mark_inode_dirty(handle, inode);
+       if (err) {
+               ext4_std_error(sb, err);
+               goto fail_free_drop;
+       }
+
        ext4_debug("allocating inode %lu\n", inode->i_ino);
        goto really_out;
 fail:
@@ -796,7 +792,7 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
 
        /* Error cases - e2fsck has already cleaned up for us */
        if (ino > max_ino) {
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "bad orphan ino %lu!  e2fsck was run?", ino);
                goto error;
        }
@@ -805,7 +801,7 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
        bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb);
        bitmap_bh = read_inode_bitmap(sb, block_group);
        if (!bitmap_bh) {
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "inode bitmap error for orphan %lu", ino);
                goto error;
        }
@@ -830,7 +826,7 @@ iget_failed:
        err = PTR_ERR(inode);
        inode = NULL;
 bad_orphan:
-       ext4_warning(sb, __FUNCTION__,
+       ext4_warning(sb, __func__,
                     "bad orphan inode %lu!  e2fsck was run?", ino);
        printk(KERN_NOTICE "ext4_test_bit(bit=%d, block=%llu) = %d\n",
               bit, (unsigned long long)bitmap_bh->b_blocknr,
index 8fab233cb05fd6bdc8538c7ee4ad6990c2fded70..8d9707746413d90bc5bf019ea6e2dacad91842c2 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/time.h>
-#include <linux/ext4_jbd2.h>
 #include <linux/jbd2.h>
 #include <linux/highuid.h>
 #include <linux/pagemap.h>
@@ -36,6 +35,7 @@
 #include <linux/mpage.h>
 #include <linux/uio.h>
 #include <linux/bio.h>
+#include "ext4_jbd2.h"
 #include "xattr.h"
 #include "acl.h"
 
@@ -93,7 +93,7 @@ int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode,
        BUFFER_TRACE(bh, "call ext4_journal_revoke");
        err = ext4_journal_revoke(handle, blocknr, bh);
        if (err)
-               ext4_abort(inode->i_sb, __FUNCTION__,
+               ext4_abort(inode->i_sb, __func__,
                           "error %d when attempting revoke", err);
        BUFFER_TRACE(bh, "exit");
        return err;
@@ -985,6 +985,16 @@ int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block,
        } else {
                retval = ext4_get_blocks_handle(handle, inode, block,
                                max_blocks, bh, create, extend_disksize);
+
+               if (retval > 0 && buffer_new(bh)) {
+                       /*
+                        * We allocated new blocks which will result in
+                        * i_data's format changing.  Force the migrate
+                        * to fail by clearing migrate flags
+                        */
+                       EXT4_I(inode)->i_flags = EXT4_I(inode)->i_flags &
+                                                       ~EXT4_EXT_MIGRATE;
+               }
        }
        up_write((&EXT4_I(inode)->i_data_sem));
        return retval;
@@ -1230,7 +1240,7 @@ int ext4_journal_dirty_data(handle_t *handle, struct buffer_head *bh)
 {
        int err = jbd2_journal_dirty_data(handle, bh);
        if (err)
-               ext4_journal_abort_handle(__FUNCTION__, __FUNCTION__,
+               ext4_journal_abort_handle(__func__, __func__,
                                                bh, handle, err);
        return err;
 }
@@ -1301,10 +1311,11 @@ static int ext4_ordered_write_end(struct file *file,
                new_i_size = pos + copied;
                if (new_i_size > EXT4_I(inode)->i_disksize)
                        EXT4_I(inode)->i_disksize = new_i_size;
-               copied = ext4_generic_write_end(file, mapping, pos, len, copied,
+               ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
                                                        page, fsdata);
-               if (copied < 0)
-                       ret = copied;
+               copied = ret2;
+               if (ret2 < 0)
+                       ret = ret2;
        }
        ret2 = ext4_journal_stop(handle);
        if (!ret)
@@ -1329,10 +1340,11 @@ static int ext4_writeback_write_end(struct file *file,
        if (new_i_size > EXT4_I(inode)->i_disksize)
                EXT4_I(inode)->i_disksize = new_i_size;
 
-       copied = ext4_generic_write_end(file, mapping, pos, len, copied,
+       ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
                                                        page, fsdata);
-       if (copied < 0)
-               ret = copied;
+       copied = ret2;
+       if (ret2 < 0)
+               ret = ret2;
 
        ret2 = ext4_journal_stop(handle);
        if (!ret)
@@ -2501,12 +2513,10 @@ out_stop:
 static ext4_fsblk_t ext4_get_inode_block(struct super_block *sb,
                unsigned long ino, struct ext4_iloc *iloc)
 {
-       unsigned long desc, group_desc;
        ext4_group_t block_group;
        unsigned long offset;
        ext4_fsblk_t block;
-       struct buffer_head *bh;
-       struct ext4_group_desc * gdp;
+       struct ext4_group_desc *gdp;
 
        if (!ext4_valid_inum(sb, ino)) {
                /*
@@ -2518,22 +2528,10 @@ static ext4_fsblk_t ext4_get_inode_block(struct super_block *sb,
        }
 
        block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
-       if (block_group >= EXT4_SB(sb)->s_groups_count) {
-               ext4_error(sb,"ext4_get_inode_block","group >= groups count");
+       gdp = ext4_get_group_desc(sb, block_group, NULL);
+       if (!gdp)
                return 0;
-       }
-       smp_rmb();
-       group_desc = block_group >> EXT4_DESC_PER_BLOCK_BITS(sb);
-       desc = block_group & (EXT4_DESC_PER_BLOCK(sb) - 1);
-       bh = EXT4_SB(sb)->s_group_desc[group_desc];
-       if (!bh) {
-               ext4_error (sb, "ext4_get_inode_block",
-                           "Descriptor not loaded");
-               return 0;
-       }
 
-       gdp = (struct ext4_group_desc *)((__u8 *)bh->b_data +
-               desc * EXT4_DESC_SIZE(sb));
        /*
         * Figure out the offset within the block group inode table
         */
@@ -2976,7 +2974,8 @@ static int ext4_do_update_inode(handle_t *handle,
        if (ext4_inode_blocks_set(handle, raw_inode, ei))
                goto out_brelse;
        raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
-       raw_inode->i_flags = cpu_to_le32(ei->i_flags);
+       /* clear the migrate flag in the raw_inode */
+       raw_inode->i_flags = cpu_to_le32(ei->i_flags & ~EXT4_EXT_MIGRATE);
        if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
            cpu_to_le32(EXT4_OS_HURD))
                raw_inode->i_file_acl_high =
@@ -3374,7 +3373,7 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode)
                                EXT4_I(inode)->i_state |= EXT4_STATE_NO_EXPAND;
                                if (mnt_count !=
                                        le16_to_cpu(sbi->s_es->s_mnt_count)) {
-                                       ext4_warning(inode->i_sb, __FUNCTION__,
+                                       ext4_warning(inode->i_sb, __func__,
                                        "Unable to expand inode %lu. Delete"
                                        " some EAs or run e2fsck.",
                                        inode->i_ino);
@@ -3415,7 +3414,7 @@ void ext4_dirty_inode(struct inode *inode)
                current_handle->h_transaction != handle->h_transaction) {
                /* This task has a transaction open against a different fs */
                printk(KERN_EMERG "%s: transactions do not match!\n",
-                      __FUNCTION__);
+                      __func__);
        } else {
                jbd_debug(5, "marking dirty.  outer handle=%p\n",
                                current_handle);
index 25b13ede8086c606a4b1320c2a364889434c7b7c..7a6c2f1faba607e4a41b5d2d10b3c7f39655268f 100644 (file)
 #include <linux/fs.h>
 #include <linux/jbd2.h>
 #include <linux/capability.h>
-#include <linux/ext4_fs.h>
-#include <linux/ext4_jbd2.h>
 #include <linux/time.h>
 #include <linux/compat.h>
 #include <linux/smp_lock.h>
 #include <linux/mount.h>
 #include <asm/uaccess.h>
+#include "ext4_jbd2.h"
+#include "ext4.h"
 
-int ext4_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
-               unsigned long arg)
+long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
+       struct inode *inode = filp->f_dentry->d_inode;
        struct ext4_inode_info *ei = EXT4_I(inode);
        unsigned int flags;
        unsigned short rsv_window_size;
@@ -277,9 +277,6 @@ setversion_out:
 #ifdef CONFIG_COMPAT
 long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       struct inode *inode = file->f_path.dentry->d_inode;
-       int ret;
-
        /* These are just misnamed, they actually get/put from/to user an int */
        switch (cmd) {
        case EXT4_IOC32_GETFLAGS:
@@ -319,9 +316,6 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        default:
                return -ENOIOCTLCMD;
        }
-       lock_kernel();
-       ret = ext4_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg));
-       unlock_kernel();
-       return ret;
+       return ext4_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
 }
 #endif
index ef97f19c2f9d7a51d68ccb281ca982e79a53e823..fbec2ef93797efb9bf6ac16f2a9465fc198dc018 100644 (file)
  * mballoc.c contains the multiblocks allocation routines
  */
 
-#include <linux/time.h>
-#include <linux/fs.h>
-#include <linux/namei.h>
-#include <linux/ext4_jbd2.h>
-#include <linux/ext4_fs.h>
-#include <linux/quotaops.h>
-#include <linux/buffer_head.h>
-#include <linux/module.h>
-#include <linux/swap.h>
-#include <linux/proc_fs.h>
-#include <linux/pagemap.h>
-#include <linux/seq_file.h>
-#include <linux/version.h>
-#include "group.h"
-
+#include "mballoc.h"
 /*
  * MUSTDO:
  *   - test ext4_ext_search_left() and ext4_ext_search_right()
  *
  */
 
-/*
- * with AGGRESSIVE_CHECK allocator runs consistency checks over
- * structures. these checks slow things down a lot
- */
-#define AGGRESSIVE_CHECK__
-
-/*
- * with DOUBLE_CHECK defined mballoc creates persistent in-core
- * bitmaps, maintains and uses them to check for double allocations
- */
-#define DOUBLE_CHECK__
-
-/*
- */
-#define MB_DEBUG__
-#ifdef MB_DEBUG
-#define mb_debug(fmt, a...)    printk(fmt, ##a)
-#else
-#define mb_debug(fmt, a...)
-#endif
-
-/*
- * with EXT4_MB_HISTORY mballoc stores last N allocations in memory
- * and you can monitor it in /proc/fs/ext4/<dev>/mb_history
- */
-#define EXT4_MB_HISTORY
-#define EXT4_MB_HISTORY_ALLOC          1       /* allocation */
-#define EXT4_MB_HISTORY_PREALLOC       2       /* preallocated blocks used */
-#define EXT4_MB_HISTORY_DISCARD                4       /* preallocation discarded */
-#define EXT4_MB_HISTORY_FREE           8       /* free */
-
-#define EXT4_MB_HISTORY_DEFAULT                (EXT4_MB_HISTORY_ALLOC | \
-                                        EXT4_MB_HISTORY_PREALLOC)
-
-/*
- * How long mballoc can look for a best extent (in found extents)
- */
-#define MB_DEFAULT_MAX_TO_SCAN         200
-
-/*
- * How long mballoc must look for a best extent
- */
-#define MB_DEFAULT_MIN_TO_SCAN         10
-
-/*
- * How many groups mballoc will scan looking for the best chunk
- */
-#define MB_DEFAULT_MAX_GROUPS_TO_SCAN  5
-
-/*
- * with 'ext4_mb_stats' allocator will collect stats that will be
- * shown at umount. The collecting costs though!
- */
-#define MB_DEFAULT_STATS               1
-
-/*
- * files smaller than MB_DEFAULT_STREAM_THRESHOLD are served
- * by the stream allocator, which purpose is to pack requests
- * as close each to other as possible to produce smooth I/O traffic
- * We use locality group prealloc space for stream request.
- * We can tune the same via /proc/fs/ext4/<parition>/stream_req
- */
-#define MB_DEFAULT_STREAM_THRESHOLD    16      /* 64K */
-
-/*
- * for which requests use 2^N search using buddies
- */
-#define MB_DEFAULT_ORDER2_REQS         2
-
-/*
- * default group prealloc size 512 blocks
- */
-#define MB_DEFAULT_GROUP_PREALLOC      512
-
-static struct kmem_cache *ext4_pspace_cachep;
-static struct kmem_cache *ext4_ac_cachep;
-
-#ifdef EXT4_BB_MAX_BLOCKS
-#undef EXT4_BB_MAX_BLOCKS
-#endif
-#define EXT4_BB_MAX_BLOCKS     30
-
-struct ext4_free_metadata {
-       ext4_group_t group;
-       unsigned short num;
-       ext4_grpblk_t  blocks[EXT4_BB_MAX_BLOCKS];
-       struct list_head list;
-};
-
-struct ext4_group_info {
-       unsigned long   bb_state;
-       unsigned long   bb_tid;
-       struct ext4_free_metadata *bb_md_cur;
-       unsigned short  bb_first_free;
-       unsigned short  bb_free;
-       unsigned short  bb_fragments;
-       struct          list_head bb_prealloc_list;
-#ifdef DOUBLE_CHECK
-       void            *bb_bitmap;
-#endif
-       unsigned short  bb_counters[];
-};
-
-#define EXT4_GROUP_INFO_NEED_INIT_BIT  0
-#define EXT4_GROUP_INFO_LOCKED_BIT     1
-
-#define EXT4_MB_GRP_NEED_INIT(grp)     \
-       (test_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &((grp)->bb_state)))
-
-
-struct ext4_prealloc_space {
-       struct list_head        pa_inode_list;
-       struct list_head        pa_group_list;
-       union {
-               struct list_head pa_tmp_list;
-               struct rcu_head pa_rcu;
-       } u;
-       spinlock_t              pa_lock;
-       atomic_t                pa_count;
-       unsigned                pa_deleted;
-       ext4_fsblk_t            pa_pstart;      /* phys. block */
-       ext4_lblk_t             pa_lstart;      /* log. block */
-       unsigned short          pa_len;         /* len of preallocated chunk */
-       unsigned short          pa_free;        /* how many blocks are free */
-       unsigned short          pa_linear;      /* consumed in one direction
-                                                * strictly, for grp prealloc */
-       spinlock_t              *pa_obj_lock;
-       struct inode            *pa_inode;      /* hack, for history only */
-};
-
-
-struct ext4_free_extent {
-       ext4_lblk_t fe_logical;
-       ext4_grpblk_t fe_start;
-       ext4_group_t fe_group;
-       int fe_len;
-};
-
-/*
- * Locality group:
- *   we try to group all related changes together
- *   so that writeback can flush/allocate them together as well
- */
-struct ext4_locality_group {
-       /* for allocator */
-       struct mutex            lg_mutex;       /* to serialize allocates */
-       struct list_head        lg_prealloc_list;/* list of preallocations */
-       spinlock_t              lg_prealloc_lock;
-};
-
-struct ext4_allocation_context {
-       struct inode *ac_inode;
-       struct super_block *ac_sb;
-
-       /* original request */
-       struct ext4_free_extent ac_o_ex;
-
-       /* goal request (after normalization) */
-       struct ext4_free_extent ac_g_ex;
-
-       /* the best found extent */
-       struct ext4_free_extent ac_b_ex;
-
-       /* copy of the bext found extent taken before preallocation efforts */
-       struct ext4_free_extent ac_f_ex;
-
-       /* number of iterations done. we have to track to limit searching */
-       unsigned long ac_ex_scanned;
-       __u16 ac_groups_scanned;
-       __u16 ac_found;
-       __u16 ac_tail;
-       __u16 ac_buddy;
-       __u16 ac_flags;         /* allocation hints */
-       __u8 ac_status;
-       __u8 ac_criteria;
-       __u8 ac_repeats;
-       __u8 ac_2order;         /* if request is to allocate 2^N blocks and
-                                * N > 0, the field stores N, otherwise 0 */
-       __u8 ac_op;             /* operation, for history only */
-       struct page *ac_bitmap_page;
-       struct page *ac_buddy_page;
-       struct ext4_prealloc_space *ac_pa;
-       struct ext4_locality_group *ac_lg;
-};
-
-#define AC_STATUS_CONTINUE     1
-#define AC_STATUS_FOUND                2
-#define AC_STATUS_BREAK                3
-
-struct ext4_mb_history {
-       struct ext4_free_extent orig;   /* orig allocation */
-       struct ext4_free_extent goal;   /* goal allocation */
-       struct ext4_free_extent result; /* result allocation */
-       unsigned pid;
-       unsigned ino;
-       __u16 found;    /* how many extents have been found */
-       __u16 groups;   /* how many groups have been scanned */
-       __u16 tail;     /* what tail broke some buddy */
-       __u16 buddy;    /* buddy the tail ^^^ broke */
-       __u16 flags;
-       __u8 cr:3;      /* which phase the result extent was found at */
-       __u8 op:4;
-       __u8 merged:1;
-};
-
-struct ext4_buddy {
-       struct page *bd_buddy_page;
-       void *bd_buddy;
-       struct page *bd_bitmap_page;
-       void *bd_bitmap;
-       struct ext4_group_info *bd_info;
-       struct super_block *bd_sb;
-       __u16 bd_blkbits;
-       ext4_group_t bd_group;
-};
-#define EXT4_MB_BITMAP(e4b)    ((e4b)->bd_bitmap)
-#define EXT4_MB_BUDDY(e4b)     ((e4b)->bd_buddy)
-
-#ifndef EXT4_MB_HISTORY
-static inline void ext4_mb_store_history(struct ext4_allocation_context *ac)
-{
-       return;
-}
-#else
-static void ext4_mb_store_history(struct ext4_allocation_context *ac);
-#endif
-
-#define in_range(b, first, len)        ((b) >= (first) && (b) <= (first) + (len) - 1)
-
-static struct proc_dir_entry *proc_root_ext4;
-struct buffer_head *read_block_bitmap(struct super_block *, ext4_group_t);
-ext4_fsblk_t ext4_new_blocks_old(handle_t *handle, struct inode *inode,
-                       ext4_fsblk_t goal, unsigned long *count, int *errp);
-
-static void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap,
-                                       ext4_group_t group);
-static void ext4_mb_poll_new_transaction(struct super_block *, handle_t *);
-static void ext4_mb_free_committed_blocks(struct super_block *);
-static void ext4_mb_return_to_preallocation(struct inode *inode,
-                                       struct ext4_buddy *e4b, sector_t block,
-                                       int count);
-static void ext4_mb_put_pa(struct ext4_allocation_context *,
-                       struct super_block *, struct ext4_prealloc_space *pa);
-static int ext4_mb_init_per_dev_proc(struct super_block *sb);
-static int ext4_mb_destroy_per_dev_proc(struct super_block *sb);
-
-
-static inline void ext4_lock_group(struct super_block *sb, ext4_group_t group)
-{
-       struct ext4_group_info *grinfo = ext4_get_group_info(sb, group);
-
-       bit_spin_lock(EXT4_GROUP_INFO_LOCKED_BIT, &(grinfo->bb_state));
-}
-
-static inline void ext4_unlock_group(struct super_block *sb,
-                                       ext4_group_t group)
-{
-       struct ext4_group_info *grinfo = ext4_get_group_info(sb, group);
-
-       bit_spin_unlock(EXT4_GROUP_INFO_LOCKED_BIT, &(grinfo->bb_state));
-}
-
-static inline int ext4_is_group_locked(struct super_block *sb,
-                                       ext4_group_t group)
-{
-       struct ext4_group_info *grinfo = ext4_get_group_info(sb, group);
-
-       return bit_spin_is_locked(EXT4_GROUP_INFO_LOCKED_BIT,
-                                               &(grinfo->bb_state));
-}
-
-static ext4_fsblk_t ext4_grp_offs_to_block(struct super_block *sb,
-                                       struct ext4_free_extent *fex)
-{
-       ext4_fsblk_t block;
-
-       block = (ext4_fsblk_t) fex->fe_group * EXT4_BLOCKS_PER_GROUP(sb)
-                       + fex->fe_start
-                       + le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
-       return block;
-}
-
 static inline void *mb_correct_addr_and_bit(int *bit, void *addr)
 {
 #if BITS_PER_LONG == 64
@@ -736,7 +440,7 @@ static void mb_free_blocks_double(struct inode *inode, struct ext4_buddy *e4b,
                        blocknr +=
                            le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
 
-                       ext4_error(sb, __FUNCTION__, "double-free of inode"
+                       ext4_error(sb, __func__, "double-free of inode"
                                   " %lu's block %llu(bit %u in group %lu)\n",
                                   inode ? inode->i_ino : 0, blocknr,
                                   first + i, e4b->bd_group);
@@ -898,17 +602,17 @@ static int __mb_check_buddy(struct ext4_buddy *e4b, char *file,
        list_for_each(cur, &grp->bb_prealloc_list) {
                ext4_group_t groupnr;
                struct ext4_prealloc_space *pa;
-               pa = list_entry(cur, struct ext4_prealloc_space, group_list);
-               ext4_get_group_no_and_offset(sb, pa->pstart, &groupnr, &k);
+               pa = list_entry(cur, struct ext4_prealloc_space, pa_group_list);
+               ext4_get_group_no_and_offset(sb, pa->pa_pstart, &groupnr, &k);
                MB_CHECK_ASSERT(groupnr == e4b->bd_group);
-               for (i = 0; i < pa->len; i++)
+               for (i = 0; i < pa->pa_len; i++)
                        MB_CHECK_ASSERT(mb_test_bit(k + i, buddy));
        }
        return 0;
 }
 #undef MB_CHECK_ASSERT
 #define mb_check_buddy(e4b) __mb_check_buddy(e4b,      \
-                                       __FILE__, __FUNCTION__, __LINE__)
+                                       __FILE__, __func__, __LINE__)
 #else
 #define mb_check_buddy(e4b)
 #endif
@@ -982,7 +686,7 @@ static void ext4_mb_generate_buddy(struct super_block *sb,
        grp->bb_fragments = fragments;
 
        if (free != grp->bb_free) {
-               ext4_error(sb, __FUNCTION__,
+               ext4_error(sb, __func__,
                        "EXT4-fs: group %lu: %u blocks in bitmap, %u in gd\n",
                        group, free, grp->bb_free);
                /*
@@ -1168,8 +872,9 @@ out:
        return err;
 }
 
-static int ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
-               struct ext4_buddy *e4b)
+static noinline_for_stack int
+ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
+                                       struct ext4_buddy *e4b)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct inode *inode = sbi->s_buddy_cache;
@@ -1367,7 +1072,7 @@ static int mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
                        blocknr +=
                            le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
 
-                       ext4_error(sb, __FUNCTION__, "double-free of inode"
+                       ext4_error(sb, __func__, "double-free of inode"
                                   " %lu's block %llu(bit %u in group %lu)\n",
                                   inode ? inode->i_ino : 0, blocknr, block,
                                   e4b->bd_group);
@@ -1848,7 +1553,7 @@ static void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
                         * free blocks even though group info says we
                         * we have free blocks
                         */
-                       ext4_error(sb, __FUNCTION__, "%d free blocks as per "
+                       ext4_error(sb, __func__, "%d free blocks as per "
                                        "group info. But bitmap says 0\n",
                                        free);
                        break;
@@ -1857,7 +1562,7 @@ static void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
                mb_find_extent(e4b, 0, i, ac->ac_g_ex.fe_len, &ex);
                BUG_ON(ex.fe_len <= 0);
                if (free < ex.fe_len) {
-                       ext4_error(sb, __FUNCTION__, "%d free blocks as per "
+                       ext4_error(sb, __func__, "%d free blocks as per "
                                        "group info. But got %d blocks\n",
                                        free, ex.fe_len);
                        /*
@@ -1965,7 +1670,8 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac,
        return 0;
 }
 
-static int ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
+static noinline_for_stack int
+ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
 {
        ext4_group_t group;
        ext4_group_t i;
@@ -2449,17 +2155,10 @@ static void ext4_mb_history_init(struct super_block *sb)
        int i;
 
        if (sbi->s_mb_proc != NULL) {
-               struct proc_dir_entry *p;
-               p = create_proc_entry("mb_history", S_IRUGO, sbi->s_mb_proc);
-               if (p) {
-                       p->proc_fops = &ext4_mb_seq_history_fops;
-                       p->data = sb;
-               }
-               p = create_proc_entry("mb_groups", S_IRUGO, sbi->s_mb_proc);
-               if (p) {
-                       p->proc_fops = &ext4_mb_seq_groups_fops;
-                       p->data = sb;
-               }
+               proc_create_data("mb_history", S_IRUGO, sbi->s_mb_proc,
+                                &ext4_mb_seq_history_fops, sb);
+               proc_create_data("mb_groups", S_IRUGO, sbi->s_mb_proc,
+                                &ext4_mb_seq_groups_fops, sb);
        }
 
        sbi->s_mb_history_max = 1000;
@@ -2472,7 +2171,8 @@ static void ext4_mb_history_init(struct super_block *sb)
        /* if we can't allocate history, then we simple won't use it */
 }
 
-static void ext4_mb_store_history(struct ext4_allocation_context *ac)
+static noinline_for_stack void
+ext4_mb_store_history(struct ext4_allocation_context *ac)
 {
        struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
        struct ext4_mb_history h;
@@ -2572,13 +2272,13 @@ static int ext4_mb_init_backend(struct super_block *sb)
                meta_group_info[j] = kzalloc(len, GFP_KERNEL);
                if (meta_group_info[j] == NULL) {
                        printk(KERN_ERR "EXT4-fs: can't allocate buddy mem\n");
-                       i--;
                        goto err_freebuddy;
                }
                desc = ext4_get_group_desc(sb, i, NULL);
                if (desc == NULL) {
                        printk(KERN_ERR
                                "EXT4-fs: can't read descriptor %lu\n", i);
+                       i++;
                        goto err_freebuddy;
                }
                memset(meta_group_info[j], 0, len);
@@ -2618,13 +2318,11 @@ static int ext4_mb_init_backend(struct super_block *sb)
        return 0;
 
 err_freebuddy:
-       while (i >= 0) {
+       while (i-- > 0)
                kfree(ext4_get_group_info(sb, i));
-               i--;
-       }
        i = num_meta_group_infos;
 err_freemeta:
-       while (--i >= 0)
+       while (i-- > 0)
                kfree(sbi->s_group_info[i]);
        iput(sbi->s_buddy_cache);
 err_freesgi:
@@ -2808,7 +2506,8 @@ int ext4_mb_release(struct super_block *sb)
        return 0;
 }
 
-static void ext4_mb_free_committed_blocks(struct super_block *sb)
+static noinline_for_stack void
+ext4_mb_free_committed_blocks(struct super_block *sb)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        int err;
@@ -2867,7 +2566,6 @@ static void ext4_mb_free_committed_blocks(struct super_block *sb)
        mb_debug("freed %u blocks in %u structures\n", count, count2);
 }
 
-#define EXT4_ROOT                      "ext4"
 #define EXT4_MB_STATS_NAME             "stats"
 #define EXT4_MB_MAX_TO_SCAN_NAME       "max_to_scan"
 #define EXT4_MB_MIN_TO_SCAN_NAME       "min_to_scan"
@@ -3007,9 +2705,9 @@ int __init init_ext4_mballoc(void)
                return -ENOMEM;
        }
 #ifdef CONFIG_PROC_FS
-       proc_root_ext4 = proc_mkdir(EXT4_ROOT, proc_root_fs);
+       proc_root_ext4 = proc_mkdir("fs/ext4", NULL);
        if (proc_root_ext4 == NULL)
-               printk(KERN_ERR "EXT4-fs: Unable to create %s\n", EXT4_ROOT);
+               printk(KERN_ERR "EXT4-fs: Unable to create fs/ext4\n");
 #endif
        return 0;
 }
@@ -3020,7 +2718,7 @@ void exit_ext4_mballoc(void)
        kmem_cache_destroy(ext4_pspace_cachep);
        kmem_cache_destroy(ext4_ac_cachep);
 #ifdef CONFIG_PROC_FS
-       remove_proc_entry(EXT4_ROOT, proc_root_fs);
+       remove_proc_entry("fs/ext4", NULL);
 #endif
 }
 
@@ -3029,7 +2727,8 @@ void exit_ext4_mballoc(void)
  * Check quota and mark choosed space (ac->ac_b_ex) non-free in bitmaps
  * Returns 0 if success or error code
  */
-static int ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
+static noinline_for_stack int
+ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
                                handle_t *handle)
 {
        struct buffer_head *bitmap_bh = NULL;
@@ -3078,7 +2777,7 @@ static int ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
                        in_range(block, ext4_inode_table(sb, gdp),
                                EXT4_SB(sb)->s_itb_per_group)) {
 
-               ext4_error(sb, __FUNCTION__,
+               ext4_error(sb, __func__,
                           "Allocating block in system zone - block = %llu",
                           block);
        }
@@ -3102,9 +2801,7 @@ static int ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
                                                ac->ac_b_ex.fe_group,
                                                gdp));
        }
-       gdp->bg_free_blocks_count =
-               cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)
-                               - ac->ac_b_ex.fe_len);
+       le16_add_cpu(&gdp->bg_free_blocks_count, -ac->ac_b_ex.fe_len);
        gdp->bg_checksum = ext4_group_desc_csum(sbi, ac->ac_b_ex.fe_group, gdp);
        spin_unlock(sb_bgl_lock(sbi, ac->ac_b_ex.fe_group));
        percpu_counter_sub(&sbi->s_freeblocks_counter, ac->ac_b_ex.fe_len);
@@ -3138,7 +2835,7 @@ static void ext4_mb_normalize_group_request(struct ext4_allocation_context *ac)
                ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_stripe;
        else
                ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_mb_group_prealloc;
-       mb_debug("#%u: goal %lu blocks for locality group\n",
+       mb_debug("#%u: goal %u blocks for locality group\n",
                current->pid, ac->ac_g_ex.fe_len);
 }
 
@@ -3146,15 +2843,16 @@ static void ext4_mb_normalize_group_request(struct ext4_allocation_context *ac)
  * Normalization means making request better in terms of
  * size and alignment
  */
-static void ext4_mb_normalize_request(struct ext4_allocation_context *ac,
+static noinline_for_stack void
+ext4_mb_normalize_request(struct ext4_allocation_context *ac,
                                struct ext4_allocation_request *ar)
 {
        int bsbits, max;
        ext4_lblk_t end;
-       struct list_head *cur;
        loff_t size, orig_size, start_off;
        ext4_lblk_t start, orig_start;
        struct ext4_inode_info *ei = EXT4_I(ac->ac_inode);
+       struct ext4_prealloc_space *pa;
 
        /* do normalize only data requests, metadata requests
           do not need preallocation */
@@ -3240,12 +2938,9 @@ static void ext4_mb_normalize_request(struct ext4_allocation_context *ac,
 
        /* check we don't cross already preallocated blocks */
        rcu_read_lock();
-       list_for_each_rcu(cur, &ei->i_prealloc_list) {
-               struct ext4_prealloc_space *pa;
+       list_for_each_entry_rcu(pa, &ei->i_prealloc_list, pa_inode_list) {
                unsigned long pa_end;
 
-               pa = list_entry(cur, struct ext4_prealloc_space, pa_inode_list);
-
                if (pa->pa_deleted)
                        continue;
                spin_lock(&pa->pa_lock);
@@ -3287,10 +2982,8 @@ static void ext4_mb_normalize_request(struct ext4_allocation_context *ac,
 
        /* XXX: extra loop to check we really don't overlap preallocations */
        rcu_read_lock();
-       list_for_each_rcu(cur, &ei->i_prealloc_list) {
-               struct ext4_prealloc_space *pa;
+       list_for_each_entry_rcu(pa, &ei->i_prealloc_list, pa_inode_list) {
                unsigned long pa_end;
-               pa = list_entry(cur, struct ext4_prealloc_space, pa_inode_list);
                spin_lock(&pa->pa_lock);
                if (pa->pa_deleted == 0) {
                        pa_end = pa->pa_lstart + pa->pa_len;
@@ -3382,7 +3075,7 @@ static void ext4_mb_use_inode_pa(struct ext4_allocation_context *ac,
        BUG_ON(pa->pa_free < len);
        pa->pa_free -= len;
 
-       mb_debug("use %llu/%lu from inode pa %p\n", start, len, pa);
+       mb_debug("use %llu/%u from inode pa %p\n", start, len, pa);
 }
 
 /*
@@ -3412,12 +3105,12 @@ static void ext4_mb_use_group_pa(struct ext4_allocation_context *ac,
 /*
  * search goal blocks in preallocated space
  */
-static int ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
+static noinline_for_stack int
+ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
 {
        struct ext4_inode_info *ei = EXT4_I(ac->ac_inode);
        struct ext4_locality_group *lg;
        struct ext4_prealloc_space *pa;
-       struct list_head *cur;
 
        /* only data can be preallocated */
        if (!(ac->ac_flags & EXT4_MB_HINT_DATA))
@@ -3425,8 +3118,7 @@ static int ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
 
        /* first, try per-file preallocation */
        rcu_read_lock();
-       list_for_each_rcu(cur, &ei->i_prealloc_list) {
-               pa = list_entry(cur, struct ext4_prealloc_space, pa_inode_list);
+       list_for_each_entry_rcu(pa, &ei->i_prealloc_list, pa_inode_list) {
 
                /* all fields in this condition don't change,
                 * so we can skip locking for them */
@@ -3458,8 +3150,7 @@ static int ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
                return 0;
 
        rcu_read_lock();
-       list_for_each_rcu(cur, &lg->lg_prealloc_list) {
-               pa = list_entry(cur, struct ext4_prealloc_space, pa_inode_list);
+       list_for_each_entry_rcu(pa, &lg->lg_prealloc_list, pa_inode_list) {
                spin_lock(&pa->pa_lock);
                if (pa->pa_deleted == 0 && pa->pa_free >= ac->ac_o_ex.fe_len) {
                        atomic_inc(&pa->pa_count);
@@ -3579,7 +3270,8 @@ static void ext4_mb_put_pa(struct ext4_allocation_context *ac,
 /*
  * creates new preallocated space for given inode
  */
-static int ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
+static noinline_for_stack int
+ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
 {
        struct super_block *sb = ac->ac_sb;
        struct ext4_prealloc_space *pa;
@@ -3666,7 +3358,8 @@ static int ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
 /*
  * creates new preallocated space for locality group inodes belongs to
  */
-static int ext4_mb_new_group_pa(struct ext4_allocation_context *ac)
+static noinline_for_stack int
+ext4_mb_new_group_pa(struct ext4_allocation_context *ac)
 {
        struct super_block *sb = ac->ac_sb;
        struct ext4_locality_group *lg;
@@ -3739,11 +3432,11 @@ static int ext4_mb_new_preallocation(struct ext4_allocation_context *ac)
  * the caller MUST hold group/inode locks.
  * TODO: optimize the case when there are no in-core structures yet
  */
-static int ext4_mb_release_inode_pa(struct ext4_buddy *e4b,
-                               struct buffer_head *bitmap_bh,
-                               struct ext4_prealloc_space *pa)
+static noinline_for_stack int
+ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
+                       struct ext4_prealloc_space *pa,
+                       struct ext4_allocation_context *ac)
 {
-       struct ext4_allocation_context *ac;
        struct super_block *sb = e4b->bd_sb;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        unsigned long end;
@@ -3759,8 +3452,6 @@ static int ext4_mb_release_inode_pa(struct ext4_buddy *e4b,
        BUG_ON(group != e4b->bd_group && pa->pa_len != 0);
        end = bit + pa->pa_len;
 
-       ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
-
        if (ac) {
                ac->ac_sb = sb;
                ac->ac_inode = pa->pa_inode;
@@ -3797,7 +3488,7 @@ static int ext4_mb_release_inode_pa(struct ext4_buddy *e4b,
                        pa, (unsigned long) pa->pa_lstart,
                        (unsigned long) pa->pa_pstart,
                        (unsigned long) pa->pa_len);
-               ext4_error(sb, __FUNCTION__, "free %u, pa_free %u\n",
+               ext4_error(sb, __func__, "free %u, pa_free %u\n",
                                                free, pa->pa_free);
                /*
                 * pa is already deleted so we use the value obtained
@@ -3805,22 +3496,19 @@ static int ext4_mb_release_inode_pa(struct ext4_buddy *e4b,
                 */
        }
        atomic_add(free, &sbi->s_mb_discarded);
-       if (ac)
-               kmem_cache_free(ext4_ac_cachep, ac);
 
        return err;
 }
 
-static int ext4_mb_release_group_pa(struct ext4_buddy *e4b,
-                               struct ext4_prealloc_space *pa)
+static noinline_for_stack int
+ext4_mb_release_group_pa(struct ext4_buddy *e4b,
+                               struct ext4_prealloc_space *pa,
+                               struct ext4_allocation_context *ac)
 {
-       struct ext4_allocation_context *ac;
        struct super_block *sb = e4b->bd_sb;
        ext4_group_t group;
        ext4_grpblk_t bit;
 
-       ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
-
        if (ac)
                ac->ac_op = EXT4_MB_HISTORY_DISCARD;
 
@@ -3838,7 +3526,6 @@ static int ext4_mb_release_group_pa(struct ext4_buddy *e4b,
                ac->ac_b_ex.fe_len = pa->pa_len;
                ac->ac_b_ex.fe_logical = 0;
                ext4_mb_store_history(ac);
-               kmem_cache_free(ext4_ac_cachep, ac);
        }
 
        return 0;
@@ -3853,12 +3540,14 @@ static int ext4_mb_release_group_pa(struct ext4_buddy *e4b,
  * - how many do we discard
  *   1) how many requested
  */
-static int ext4_mb_discard_group_preallocations(struct super_block *sb,
+static noinline_for_stack int
+ext4_mb_discard_group_preallocations(struct super_block *sb,
                                        ext4_group_t group, int needed)
 {
        struct ext4_group_info *grp = ext4_get_group_info(sb, group);
        struct buffer_head *bitmap_bh = NULL;
        struct ext4_prealloc_space *pa, *tmp;
+       struct ext4_allocation_context *ac;
        struct list_head list;
        struct ext4_buddy e4b;
        int err;
@@ -3886,6 +3575,7 @@ static int ext4_mb_discard_group_preallocations(struct super_block *sb,
        grp = ext4_get_group_info(sb, group);
        INIT_LIST_HEAD(&list);
 
+       ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
 repeat:
        ext4_lock_group(sb, group);
        list_for_each_entry_safe(pa, tmp,
@@ -3940,9 +3630,9 @@ repeat:
                spin_unlock(pa->pa_obj_lock);
 
                if (pa->pa_linear)
-                       ext4_mb_release_group_pa(&e4b, pa);
+                       ext4_mb_release_group_pa(&e4b, pa, ac);
                else
-                       ext4_mb_release_inode_pa(&e4b, bitmap_bh, pa);
+                       ext4_mb_release_inode_pa(&e4b, bitmap_bh, pa, ac);
 
                list_del(&pa->u.pa_tmp_list);
                call_rcu(&(pa)->u.pa_rcu, ext4_mb_pa_callback);
@@ -3950,6 +3640,8 @@ repeat:
 
 out:
        ext4_unlock_group(sb, group);
+       if (ac)
+               kmem_cache_free(ext4_ac_cachep, ac);
        ext4_mb_release_desc(&e4b);
        put_bh(bitmap_bh);
        return free;
@@ -3970,6 +3662,7 @@ void ext4_mb_discard_inode_preallocations(struct inode *inode)
        struct super_block *sb = inode->i_sb;
        struct buffer_head *bitmap_bh = NULL;
        struct ext4_prealloc_space *pa, *tmp;
+       struct ext4_allocation_context *ac;
        ext4_group_t group = 0;
        struct list_head list;
        struct ext4_buddy e4b;
@@ -3984,6 +3677,7 @@ void ext4_mb_discard_inode_preallocations(struct inode *inode)
 
        INIT_LIST_HEAD(&list);
 
+       ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
 repeat:
        /* first, collect all pa's in the inode */
        spin_lock(&ei->i_prealloc_lock);
@@ -4048,7 +3742,7 @@ repeat:
 
                ext4_lock_group(sb, group);
                list_del(&pa->pa_group_list);
-               ext4_mb_release_inode_pa(&e4b, bitmap_bh, pa);
+               ext4_mb_release_inode_pa(&e4b, bitmap_bh, pa, ac);
                ext4_unlock_group(sb, group);
 
                ext4_mb_release_desc(&e4b);
@@ -4057,6 +3751,8 @@ repeat:
                list_del(&pa->u.pa_tmp_list);
                call_rcu(&(pa)->u.pa_rcu, ext4_mb_pa_callback);
        }
+       if (ac)
+               kmem_cache_free(ext4_ac_cachep, ac);
 }
 
 /*
@@ -4116,7 +3812,7 @@ static void ext4_mb_show_ac(struct ext4_allocation_context *ac)
                        printk(KERN_ERR "PA:%lu:%d:%u \n", i,
                                                        start, pa->pa_len);
                }
-               ext4_lock_group(sb, i);
+               ext4_unlock_group(sb, i);
 
                if (grp->bb_free == 0)
                        continue;
@@ -4175,7 +3871,8 @@ static void ext4_mb_group_or_file(struct ext4_allocation_context *ac)
        mutex_lock(&ac->ac_lg->lg_mutex);
 }
 
-static int ext4_mb_initialize_context(struct ext4_allocation_context *ac,
+static noinline_for_stack int
+ext4_mb_initialize_context(struct ext4_allocation_context *ac,
                                struct ext4_allocation_request *ar)
 {
        struct super_block *sb = ar->inode->i_sb;
@@ -4406,7 +4103,8 @@ static void ext4_mb_poll_new_transaction(struct super_block *sb,
        ext4_mb_free_committed_blocks(sb);
 }
 
-static int ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
+static noinline_for_stack int
+ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
                          ext4_group_t group, ext4_grpblk_t block, int count)
 {
        struct ext4_group_info *db = e4b->bd_info;
@@ -4497,7 +4195,7 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
        if (block < le32_to_cpu(es->s_first_data_block) ||
            block + count < block ||
            block + count > ext4_blocks_count(es)) {
-               ext4_error(sb, __FUNCTION__,
+               ext4_error(sb, __func__,
                            "Freeing blocks not in datazone - "
                            "block = %lu, count = %lu", block, count);
                goto error_return;
@@ -4538,7 +4236,7 @@ do_more:
            in_range(block + count - 1, ext4_inode_table(sb, gdp),
                      EXT4_SB(sb)->s_itb_per_group)) {
 
-               ext4_error(sb, __FUNCTION__,
+               ext4_error(sb, __func__,
                           "Freeing blocks in system zone - "
                           "Block = %lu, count = %lu", block, count);
        }
@@ -4596,8 +4294,7 @@ do_more:
        }
 
        spin_lock(sb_bgl_lock(sbi, block_group));
-       gdp->bg_free_blocks_count =
-               cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) + count);
+       le16_add_cpu(&gdp->bg_free_blocks_count, count);
        gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp);
        spin_unlock(sb_bgl_lock(sbi, block_group));
        percpu_counter_add(&sbi->s_freeblocks_counter, count);
diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h
new file mode 100644 (file)
index 0000000..bfe6add
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ *  fs/ext4/mballoc.h
+ *
+ *  Written by: Alex Tomas <alex@clusterfs.com>
+ *
+ */
+#ifndef _EXT4_MBALLOC_H
+#define _EXT4_MBALLOC_H
+
+#include <linux/time.h>
+#include <linux/fs.h>
+#include <linux/namei.h>
+#include <linux/quotaops.h>
+#include <linux/buffer_head.h>
+#include <linux/module.h>
+#include <linux/swap.h>
+#include <linux/proc_fs.h>
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/version.h>
+#include "ext4_jbd2.h"
+#include "ext4.h"
+#include "group.h"
+
+/*
+ * with AGGRESSIVE_CHECK allocator runs consistency checks over
+ * structures. these checks slow things down a lot
+ */
+#define AGGRESSIVE_CHECK__
+
+/*
+ * with DOUBLE_CHECK defined mballoc creates persistent in-core
+ * bitmaps, maintains and uses them to check for double allocations
+ */
+#define DOUBLE_CHECK__
+
+/*
+ */
+#define MB_DEBUG__
+#ifdef MB_DEBUG
+#define mb_debug(fmt, a...)    printk(fmt, ##a)
+#else
+#define mb_debug(fmt, a...)
+#endif
+
+/*
+ * with EXT4_MB_HISTORY mballoc stores last N allocations in memory
+ * and you can monitor it in /proc/fs/ext4/<dev>/mb_history
+ */
+#define EXT4_MB_HISTORY
+#define EXT4_MB_HISTORY_ALLOC          1       /* allocation */
+#define EXT4_MB_HISTORY_PREALLOC       2       /* preallocated blocks used */
+#define EXT4_MB_HISTORY_DISCARD                4       /* preallocation discarded */
+#define EXT4_MB_HISTORY_FREE           8       /* free */
+
+#define EXT4_MB_HISTORY_DEFAULT                (EXT4_MB_HISTORY_ALLOC | \
+                                        EXT4_MB_HISTORY_PREALLOC)
+
+/*
+ * How long mballoc can look for a best extent (in found extents)
+ */
+#define MB_DEFAULT_MAX_TO_SCAN         200
+
+/*
+ * How long mballoc must look for a best extent
+ */
+#define MB_DEFAULT_MIN_TO_SCAN         10
+
+/*
+ * How many groups mballoc will scan looking for the best chunk
+ */
+#define MB_DEFAULT_MAX_GROUPS_TO_SCAN  5
+
+/*
+ * with 'ext4_mb_stats' allocator will collect stats that will be
+ * shown at umount. The collecting costs though!
+ */
+#define MB_DEFAULT_STATS               1
+
+/*
+ * files smaller than MB_DEFAULT_STREAM_THRESHOLD are served
+ * by the stream allocator, which purpose is to pack requests
+ * as close each to other as possible to produce smooth I/O traffic
+ * We use locality group prealloc space for stream request.
+ * We can tune the same via /proc/fs/ext4/<parition>/stream_req
+ */
+#define MB_DEFAULT_STREAM_THRESHOLD    16      /* 64K */
+
+/*
+ * for which requests use 2^N search using buddies
+ */
+#define MB_DEFAULT_ORDER2_REQS         2
+
+/*
+ * default group prealloc size 512 blocks
+ */
+#define MB_DEFAULT_GROUP_PREALLOC      512
+
+static struct kmem_cache *ext4_pspace_cachep;
+static struct kmem_cache *ext4_ac_cachep;
+
+#ifdef EXT4_BB_MAX_BLOCKS
+#undef EXT4_BB_MAX_BLOCKS
+#endif
+#define EXT4_BB_MAX_BLOCKS     30
+
+struct ext4_free_metadata {
+       ext4_group_t group;
+       unsigned short num;
+       ext4_grpblk_t  blocks[EXT4_BB_MAX_BLOCKS];
+       struct list_head list;
+};
+
+struct ext4_group_info {
+       unsigned long   bb_state;
+       unsigned long   bb_tid;
+       struct ext4_free_metadata *bb_md_cur;
+       unsigned short  bb_first_free;
+       unsigned short  bb_free;
+       unsigned short  bb_fragments;
+       struct          list_head bb_prealloc_list;
+#ifdef DOUBLE_CHECK
+       void            *bb_bitmap;
+#endif
+       unsigned short  bb_counters[];
+};
+
+#define EXT4_GROUP_INFO_NEED_INIT_BIT  0
+#define EXT4_GROUP_INFO_LOCKED_BIT     1
+
+#define EXT4_MB_GRP_NEED_INIT(grp)     \
+       (test_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &((grp)->bb_state)))
+
+
+struct ext4_prealloc_space {
+       struct list_head        pa_inode_list;
+       struct list_head        pa_group_list;
+       union {
+               struct list_head pa_tmp_list;
+               struct rcu_head pa_rcu;
+       } u;
+       spinlock_t              pa_lock;
+       atomic_t                pa_count;
+       unsigned                pa_deleted;
+       ext4_fsblk_t            pa_pstart;      /* phys. block */
+       ext4_lblk_t             pa_lstart;      /* log. block */
+       unsigned short          pa_len;         /* len of preallocated chunk */
+       unsigned short          pa_free;        /* how many blocks are free */
+       unsigned short          pa_linear;      /* consumed in one direction
+                                                * strictly, for grp prealloc */
+       spinlock_t              *pa_obj_lock;
+       struct inode            *pa_inode;      /* hack, for history only */
+};
+
+
+struct ext4_free_extent {
+       ext4_lblk_t fe_logical;
+       ext4_grpblk_t fe_start;
+       ext4_group_t fe_group;
+       int fe_len;
+};
+
+/*
+ * Locality group:
+ *   we try to group all related changes together
+ *   so that writeback can flush/allocate them together as well
+ */
+struct ext4_locality_group {
+       /* for allocator */
+       struct mutex            lg_mutex;       /* to serialize allocates */
+       struct list_head        lg_prealloc_list;/* list of preallocations */
+       spinlock_t              lg_prealloc_lock;
+};
+
+struct ext4_allocation_context {
+       struct inode *ac_inode;
+       struct super_block *ac_sb;
+
+       /* original request */
+       struct ext4_free_extent ac_o_ex;
+
+       /* goal request (after normalization) */
+       struct ext4_free_extent ac_g_ex;
+
+       /* the best found extent */
+       struct ext4_free_extent ac_b_ex;
+
+       /* copy of the bext found extent taken before preallocation efforts */
+       struct ext4_free_extent ac_f_ex;
+
+       /* number of iterations done. we have to track to limit searching */
+       unsigned long ac_ex_scanned;
+       __u16 ac_groups_scanned;
+       __u16 ac_found;
+       __u16 ac_tail;
+       __u16 ac_buddy;
+       __u16 ac_flags;         /* allocation hints */
+       __u8 ac_status;
+       __u8 ac_criteria;
+       __u8 ac_repeats;
+       __u8 ac_2order;         /* if request is to allocate 2^N blocks and
+                                * N > 0, the field stores N, otherwise 0 */
+       __u8 ac_op;             /* operation, for history only */
+       struct page *ac_bitmap_page;
+       struct page *ac_buddy_page;
+       struct ext4_prealloc_space *ac_pa;
+       struct ext4_locality_group *ac_lg;
+};
+
+#define AC_STATUS_CONTINUE     1
+#define AC_STATUS_FOUND                2
+#define AC_STATUS_BREAK                3
+
+struct ext4_mb_history {
+       struct ext4_free_extent orig;   /* orig allocation */
+       struct ext4_free_extent goal;   /* goal allocation */
+       struct ext4_free_extent result; /* result allocation */
+       unsigned pid;
+       unsigned ino;
+       __u16 found;    /* how many extents have been found */
+       __u16 groups;   /* how many groups have been scanned */
+       __u16 tail;     /* what tail broke some buddy */
+       __u16 buddy;    /* buddy the tail ^^^ broke */
+       __u16 flags;
+       __u8 cr:3;      /* which phase the result extent was found at */
+       __u8 op:4;
+       __u8 merged:1;
+};
+
+struct ext4_buddy {
+       struct page *bd_buddy_page;
+       void *bd_buddy;
+       struct page *bd_bitmap_page;
+       void *bd_bitmap;
+       struct ext4_group_info *bd_info;
+       struct super_block *bd_sb;
+       __u16 bd_blkbits;
+       ext4_group_t bd_group;
+};
+#define EXT4_MB_BITMAP(e4b)    ((e4b)->bd_bitmap)
+#define EXT4_MB_BUDDY(e4b)     ((e4b)->bd_buddy)
+
+#ifndef EXT4_MB_HISTORY
+static inline void ext4_mb_store_history(struct ext4_allocation_context *ac)
+{
+       return;
+}
+#else
+static void ext4_mb_store_history(struct ext4_allocation_context *ac);
+#endif
+
+#define in_range(b, first, len)        ((b) >= (first) && (b) <= (first) + (len) - 1)
+
+static struct proc_dir_entry *proc_root_ext4;
+struct buffer_head *read_block_bitmap(struct super_block *, ext4_group_t);
+
+static void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap,
+                                       ext4_group_t group);
+static void ext4_mb_poll_new_transaction(struct super_block *, handle_t *);
+static void ext4_mb_free_committed_blocks(struct super_block *);
+static void ext4_mb_return_to_preallocation(struct inode *inode,
+                                       struct ext4_buddy *e4b, sector_t block,
+                                       int count);
+static void ext4_mb_put_pa(struct ext4_allocation_context *,
+                       struct super_block *, struct ext4_prealloc_space *pa);
+static int ext4_mb_init_per_dev_proc(struct super_block *sb);
+static int ext4_mb_destroy_per_dev_proc(struct super_block *sb);
+
+
+static inline void ext4_lock_group(struct super_block *sb, ext4_group_t group)
+{
+       struct ext4_group_info *grinfo = ext4_get_group_info(sb, group);
+
+       bit_spin_lock(EXT4_GROUP_INFO_LOCKED_BIT, &(grinfo->bb_state));
+}
+
+static inline void ext4_unlock_group(struct super_block *sb,
+                                       ext4_group_t group)
+{
+       struct ext4_group_info *grinfo = ext4_get_group_info(sb, group);
+
+       bit_spin_unlock(EXT4_GROUP_INFO_LOCKED_BIT, &(grinfo->bb_state));
+}
+
+static inline int ext4_is_group_locked(struct super_block *sb,
+                                       ext4_group_t group)
+{
+       struct ext4_group_info *grinfo = ext4_get_group_info(sb, group);
+
+       return bit_spin_is_locked(EXT4_GROUP_INFO_LOCKED_BIT,
+                                               &(grinfo->bb_state));
+}
+
+static ext4_fsblk_t ext4_grp_offs_to_block(struct super_block *sb,
+                                       struct ext4_free_extent *fex)
+{
+       ext4_fsblk_t block;
+
+       block = (ext4_fsblk_t) fex->fe_group * EXT4_BLOCKS_PER_GROUP(sb)
+                       + fex->fe_start
+                       + le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
+       return block;
+}
+#endif
index 5c1e27de7755b46552c3fd85dd11ad66d0ec1490..b9e077ba07e94b0c979ebea4530e1fc9471e6eee 100644 (file)
@@ -13,8 +13,8 @@
  */
 
 #include <linux/module.h>
-#include <linux/ext4_jbd2.h>
-#include <linux/ext4_fs_extents.h>
+#include "ext4_jbd2.h"
+#include "ext4_extents.h"
 
 /*
  * The contiguous blocks details which can be
@@ -327,7 +327,7 @@ static int free_ind_block(handle_t *handle, struct inode *inode, __le32 *i_data)
 }
 
 static int ext4_ext_swap_inode_data(handle_t *handle, struct inode *inode,
-                               struct inode *tmp_inode)
+                                               struct inode *tmp_inode)
 {
        int retval;
        __le32  i_data[3];
@@ -339,7 +339,7 @@ static int ext4_ext_swap_inode_data(handle_t *handle, struct inode *inode,
         * i_data field of the original inode
         */
        retval = ext4_journal_extend(handle, 1);
-       if (retval != 0) {
+       if (retval) {
                retval = ext4_journal_restart(handle, 1);
                if (retval)
                        goto err_out;
@@ -350,6 +350,18 @@ static int ext4_ext_swap_inode_data(handle_t *handle, struct inode *inode,
        i_data[2] = ei->i_data[EXT4_TIND_BLOCK];
 
        down_write(&EXT4_I(inode)->i_data_sem);
+       /*
+        * if EXT4_EXT_MIGRATE is cleared a block allocation
+        * happened after we started the migrate. We need to
+        * fail the migrate
+        */
+       if (!(EXT4_I(inode)->i_flags & EXT4_EXT_MIGRATE)) {
+               retval = -EAGAIN;
+               up_write(&EXT4_I(inode)->i_data_sem);
+               goto err_out;
+       } else
+               EXT4_I(inode)->i_flags = EXT4_I(inode)->i_flags &
+                                                       ~EXT4_EXT_MIGRATE;
        /*
         * We have the extent map build with the tmp inode.
         * Now copy the i_data across
@@ -508,6 +520,17 @@ int ext4_ext_migrate(struct inode *inode, struct file *filp,
         * switch the inode format to prevent read.
         */
        mutex_lock(&(inode->i_mutex));
+       /*
+        * Even though we take i_mutex we can still cause block allocation
+        * via mmap write to holes. If we have allocated new blocks we fail
+        * migrate.  New block allocation will clear EXT4_EXT_MIGRATE flag.
+        * The flag is updated with i_data_sem held to prevent racing with
+        * block allocation.
+        */
+       down_read((&EXT4_I(inode)->i_data_sem));
+       EXT4_I(inode)->i_flags = EXT4_I(inode)->i_flags | EXT4_EXT_MIGRATE;
+       up_read((&EXT4_I(inode)->i_data_sem));
+
        handle = ext4_journal_start(inode, 1);
 
        ei = EXT4_I(inode);
@@ -559,9 +582,15 @@ err_out:
                 * tmp_inode
                 */
                free_ext_block(handle, tmp_inode);
-       else
-               retval = ext4_ext_swap_inode_data(handle, inode,
-                                                       tmp_inode);
+       else {
+               retval = ext4_ext_swap_inode_data(handle, inode, tmp_inode);
+               if (retval)
+                       /*
+                        * if we fail to swap inode data free the extent
+                        * details of the tmp inode
+                        */
+                       free_ext_block(handle, tmp_inode);
+       }
 
        /* We mark the tmp_inode dirty via ext4_ext_tree_init. */
        if (ext4_journal_extend(handle, 1) != 0)
index 28aa2ed4297ecb30aeedb1d04f3c5470410c7e9a..ab16beaa830d3814250146d044f8d2c4a59c7dd4 100644 (file)
 #include <linux/pagemap.h>
 #include <linux/jbd2.h>
 #include <linux/time.h>
-#include <linux/ext4_fs.h>
-#include <linux/ext4_jbd2.h>
 #include <linux/fcntl.h>
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/quotaops.h>
 #include <linux/buffer_head.h>
 #include <linux/bio.h>
+#include "ext4.h"
+#include "ext4_jbd2.h"
 
 #include "namei.h"
 #include "xattr.h"
@@ -57,10 +57,15 @@ static struct buffer_head *ext4_append(handle_t *handle,
 
        *block = inode->i_size >> inode->i_sb->s_blocksize_bits;
 
-       if ((bh = ext4_bread(handle, inode, *block, 1, err))) {
+       bh = ext4_bread(handle, inode, *block, 1, err);
+       if (bh) {
                inode->i_size += inode->i_sb->s_blocksize;
                EXT4_I(inode)->i_disksize = inode->i_size;
-               ext4_journal_get_write_access(handle,bh);
+               *err = ext4_journal_get_write_access(handle, bh);
+               if (*err) {
+                       brelse(bh);
+                       bh = NULL;
+               }
        }
        return bh;
 }
@@ -348,7 +353,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
        if (root->info.hash_version != DX_HASH_TEA &&
            root->info.hash_version != DX_HASH_HALF_MD4 &&
            root->info.hash_version != DX_HASH_LEGACY) {
-               ext4_warning(dir->i_sb, __FUNCTION__,
+               ext4_warning(dir->i_sb, __func__,
                             "Unrecognised inode hash code %d",
                             root->info.hash_version);
                brelse(bh);
@@ -362,7 +367,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
        hash = hinfo->hash;
 
        if (root->info.unused_flags & 1) {
-               ext4_warning(dir->i_sb, __FUNCTION__,
+               ext4_warning(dir->i_sb, __func__,
                             "Unimplemented inode hash flags: %#06x",
                             root->info.unused_flags);
                brelse(bh);
@@ -371,7 +376,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
        }
 
        if ((indirect = root->info.indirect_levels) > 1) {
-               ext4_warning(dir->i_sb, __FUNCTION__,
+               ext4_warning(dir->i_sb, __func__,
                             "Unimplemented inode hash depth: %#06x",
                             root->info.indirect_levels);
                brelse(bh);
@@ -384,7 +389,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
 
        if (dx_get_limit(entries) != dx_root_limit(dir,
                                                   root->info.info_length)) {
-               ext4_warning(dir->i_sb, __FUNCTION__,
+               ext4_warning(dir->i_sb, __func__,
                             "dx entry: limit != root limit");
                brelse(bh);
                *err = ERR_BAD_DX_DIR;
@@ -396,7 +401,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
        {
                count = dx_get_count(entries);
                if (!count || count > dx_get_limit(entries)) {
-                       ext4_warning(dir->i_sb, __FUNCTION__,
+                       ext4_warning(dir->i_sb, __func__,
                                     "dx entry: no count or count > limit");
                        brelse(bh);
                        *err = ERR_BAD_DX_DIR;
@@ -441,7 +446,7 @@ dx_probe(struct dentry *dentry, struct inode *dir,
                        goto fail2;
                at = entries = ((struct dx_node *) bh->b_data)->entries;
                if (dx_get_limit(entries) != dx_node_limit (dir)) {
-                       ext4_warning(dir->i_sb, __FUNCTION__,
+                       ext4_warning(dir->i_sb, __func__,
                                     "dx entry: limit != node limit");
                        brelse(bh);
                        *err = ERR_BAD_DX_DIR;
@@ -457,7 +462,7 @@ fail2:
        }
 fail:
        if (*err == ERR_BAD_DX_DIR)
-               ext4_warning(dir->i_sb, __FUNCTION__,
+               ext4_warning(dir->i_sb, __func__,
                             "Corrupt dir inode %ld, running e2fsck is "
                             "recommended.", dir->i_ino);
        return NULL;
@@ -914,7 +919,7 @@ restart:
                wait_on_buffer(bh);
                if (!buffer_uptodate(bh)) {
                        /* read error, skip block & hope for the best */
-                       ext4_error(sb, __FUNCTION__, "reading directory #%lu "
+                       ext4_error(sb, __func__, "reading directory #%lu "
                                   "offset %lu", dir->i_ino,
                                   (unsigned long)block);
                        brelse(bh);
@@ -1007,7 +1012,7 @@ static struct buffer_head * ext4_dx_find_entry(struct dentry *dentry,
                retval = ext4_htree_next_block(dir, hash, frame,
                                               frames, NULL);
                if (retval < 0) {
-                       ext4_warning(sb, __FUNCTION__,
+                       ext4_warning(sb, __func__,
                             "error reading index page in directory #%lu",
                             dir->i_ino);
                        *err = retval;
@@ -1532,7 +1537,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry,
 
                if (levels && (dx_get_count(frames->entries) ==
                               dx_get_limit(frames->entries))) {
-                       ext4_warning(sb, __FUNCTION__,
+                       ext4_warning(sb, __func__,
                                     "Directory index full!");
                        err = -ENOSPC;
                        goto cleanup;
@@ -1860,11 +1865,11 @@ static int empty_dir (struct inode * inode)
        if (inode->i_size < EXT4_DIR_REC_LEN(1) + EXT4_DIR_REC_LEN(2) ||
            !(bh = ext4_bread (NULL, inode, 0, 0, &err))) {
                if (err)
-                       ext4_error(inode->i_sb, __FUNCTION__,
+                       ext4_error(inode->i_sb, __func__,
                                   "error %d reading directory #%lu offset 0",
                                   err, inode->i_ino);
                else
-                       ext4_warning(inode->i_sb, __FUNCTION__,
+                       ext4_warning(inode->i_sb, __func__,
                                     "bad directory (dir #%lu) - no data block",
                                     inode->i_ino);
                return 1;
@@ -1893,7 +1898,7 @@ static int empty_dir (struct inode * inode)
                                offset >> EXT4_BLOCK_SIZE_BITS(sb), 0, &err);
                        if (!bh) {
                                if (err)
-                                       ext4_error(sb, __FUNCTION__,
+                                       ext4_error(sb, __func__,
                                                   "error %d reading directory"
                                                   " #%lu offset %lu",
                                                   err, inode->i_ino, offset);
@@ -2217,6 +2222,8 @@ retry:
                        goto out_stop;
                }
        } else {
+               /* clear the extent format for fast symlink */
+               EXT4_I(inode)->i_flags &= ~EXT4_EXTENTS_FL;
                inode->i_op = &ext4_fast_symlink_inode_operations;
                memcpy((char*)&EXT4_I(inode)->i_data,symname,l);
                inode->i_size = l-1;
@@ -2347,6 +2354,9 @@ static int ext4_rename (struct inode * old_dir, struct dentry *old_dentry,
                                              EXT4_FEATURE_INCOMPAT_FILETYPE))
                        new_de->file_type = old_de->file_type;
                new_dir->i_version++;
+               new_dir->i_ctime = new_dir->i_mtime =
+                                       ext4_current_time(new_dir);
+               ext4_mark_inode_dirty(handle, new_dir);
                BUFFER_TRACE(new_bh, "call ext4_journal_dirty_metadata");
                ext4_journal_dirty_metadata(handle, new_bh);
                brelse(new_bh);
index e29efa0f9d6298402bf35b588838d9737b08c551..9f086a6a472b1c13359334d6966caaa6a90d4ea1 100644 (file)
 
 #define EXT4FS_DEBUG
 
-#include <linux/ext4_jbd2.h>
-
 #include <linux/errno.h>
 #include <linux/slab.h>
 
+#include "ext4_jbd2.h"
 #include "group.h"
 
 #define outside(b, first, last)        ((b) < (first) || (b) >= (last))
@@ -50,63 +49,63 @@ static int verify_group_input(struct super_block *sb,
 
        ext4_get_group_no_and_offset(sb, start, NULL, &offset);
        if (group != sbi->s_groups_count)
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "Cannot add at group %u (only %lu groups)",
                             input->group, sbi->s_groups_count);
        else if (offset != 0)
-                       ext4_warning(sb, __FUNCTION__, "Last group not full");
+                       ext4_warning(sb, __func__, "Last group not full");
        else if (input->reserved_blocks > input->blocks_count / 5)
-               ext4_warning(sb, __FUNCTION__, "Reserved blocks too high (%u)",
+               ext4_warning(sb, __func__, "Reserved blocks too high (%u)",
                             input->reserved_blocks);
        else if (free_blocks_count < 0)
-               ext4_warning(sb, __FUNCTION__, "Bad blocks count %u",
+               ext4_warning(sb, __func__, "Bad blocks count %u",
                             input->blocks_count);
        else if (!(bh = sb_bread(sb, end - 1)))
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "Cannot read last block (%llu)",
                             end - 1);
        else if (outside(input->block_bitmap, start, end))
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "Block bitmap not in group (block %llu)",
                             (unsigned long long)input->block_bitmap);
        else if (outside(input->inode_bitmap, start, end))
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "Inode bitmap not in group (block %llu)",
                             (unsigned long long)input->inode_bitmap);
        else if (outside(input->inode_table, start, end) ||
                 outside(itend - 1, start, end))
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "Inode table not in group (blocks %llu-%llu)",
                             (unsigned long long)input->inode_table, itend - 1);
        else if (input->inode_bitmap == input->block_bitmap)
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "Block bitmap same as inode bitmap (%llu)",
                             (unsigned long long)input->block_bitmap);
        else if (inside(input->block_bitmap, input->inode_table, itend))
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "Block bitmap (%llu) in inode table (%llu-%llu)",
                             (unsigned long long)input->block_bitmap,
                             (unsigned long long)input->inode_table, itend - 1);
        else if (inside(input->inode_bitmap, input->inode_table, itend))
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "Inode bitmap (%llu) in inode table (%llu-%llu)",
                             (unsigned long long)input->inode_bitmap,
                             (unsigned long long)input->inode_table, itend - 1);
        else if (inside(input->block_bitmap, start, metaend))
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "Block bitmap (%llu) in GDT table"
                             " (%llu-%llu)",
                             (unsigned long long)input->block_bitmap,
                             start, metaend - 1);
        else if (inside(input->inode_bitmap, start, metaend))
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "Inode bitmap (%llu) in GDT table"
                             " (%llu-%llu)",
                             (unsigned long long)input->inode_bitmap,
                             start, metaend - 1);
        else if (inside(input->inode_table, start, metaend) ||
                 inside(itend - 1, start, metaend))
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "Inode table (%llu-%llu) overlaps"
                             "GDT table (%llu-%llu)",
                             (unsigned long long)input->inode_table,
@@ -368,7 +367,7 @@ static int verify_reserved_gdb(struct super_block *sb,
        while ((grp = ext4_list_backups(sb, &three, &five, &seven)) < end) {
                if (le32_to_cpu(*p++) !=
                    grp * EXT4_BLOCKS_PER_GROUP(sb) + blk){
-                       ext4_warning(sb, __FUNCTION__,
+                       ext4_warning(sb, __func__,
                                     "reserved GDT %llu"
                                     " missing grp %d (%llu)",
                                     blk, grp,
@@ -424,7 +423,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
         */
        if (EXT4_SB(sb)->s_sbh->b_blocknr !=
            le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) {
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                        "won't resize using backup superblock at %llu",
                        (unsigned long long)EXT4_SB(sb)->s_sbh->b_blocknr);
                return -EPERM;
@@ -448,7 +447,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
 
        data = (__le32 *)dind->b_data;
        if (le32_to_cpu(data[gdb_num % EXT4_ADDR_PER_BLOCK(sb)]) != gdblock) {
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "new group %u GDT block %llu not reserved",
                             input->group, gdblock);
                err = -EINVAL;
@@ -469,10 +468,10 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
                goto exit_dindj;
 
        n_group_desc = kmalloc((gdb_num + 1) * sizeof(struct buffer_head *),
-                       GFP_KERNEL);
+                       GFP_NOFS);
        if (!n_group_desc) {
                err = -ENOMEM;
-               ext4_warning (sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                              "not enough memory for %lu groups", gdb_num + 1);
                goto exit_inode;
        }
@@ -502,8 +501,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
        EXT4_SB(sb)->s_gdb_count++;
        kfree(o_group_desc);
 
-       es->s_reserved_gdt_blocks =
-               cpu_to_le16(le16_to_cpu(es->s_reserved_gdt_blocks) - 1);
+       le16_add_cpu(&es->s_reserved_gdt_blocks, -1);
        ext4_journal_dirty_metadata(handle, EXT4_SB(sb)->s_sbh);
 
        return 0;
@@ -553,7 +551,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
        int res, i;
        int err;
 
-       primary = kmalloc(reserved_gdb * sizeof(*primary), GFP_KERNEL);
+       primary = kmalloc(reserved_gdb * sizeof(*primary), GFP_NOFS);
        if (!primary)
                return -ENOMEM;
 
@@ -571,7 +569,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
        /* Get each reserved primary GDT block and verify it holds backups */
        for (res = 0; res < reserved_gdb; res++, blk++) {
                if (le32_to_cpu(*data) != blk) {
-                       ext4_warning(sb, __FUNCTION__,
+                       ext4_warning(sb, __func__,
                                     "reserved block %llu"
                                     " not at offset %ld",
                                     blk,
@@ -715,7 +713,7 @@ static void update_backups(struct super_block *sb,
         */
 exit_err:
        if (err) {
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "can't update backup for group %lu (err %d), "
                             "forcing fsck on next reboot", group, err);
                sbi->s_mount_state &= ~EXT4_VALID_FS;
@@ -755,33 +753,33 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
 
        if (gdb_off == 0 && !EXT4_HAS_RO_COMPAT_FEATURE(sb,
                                        EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "Can't resize non-sparse filesystem further");
                return -EPERM;
        }
 
        if (ext4_blocks_count(es) + input->blocks_count <
            ext4_blocks_count(es)) {
-               ext4_warning(sb, __FUNCTION__, "blocks_count overflow\n");
+               ext4_warning(sb, __func__, "blocks_count overflow\n");
                return -EINVAL;
        }
 
        if (le32_to_cpu(es->s_inodes_count) + EXT4_INODES_PER_GROUP(sb) <
            le32_to_cpu(es->s_inodes_count)) {
-               ext4_warning(sb, __FUNCTION__, "inodes_count overflow\n");
+               ext4_warning(sb, __func__, "inodes_count overflow\n");
                return -EINVAL;
        }
 
        if (reserved_gdb || gdb_off == 0) {
                if (!EXT4_HAS_COMPAT_FEATURE(sb,
                                             EXT4_FEATURE_COMPAT_RESIZE_INODE)){
-                       ext4_warning(sb, __FUNCTION__,
+                       ext4_warning(sb, __func__,
                                     "No reserved GDT blocks, can't resize");
                        return -EPERM;
                }
                inode = ext4_iget(sb, EXT4_RESIZE_INO);
                if (IS_ERR(inode)) {
-                       ext4_warning(sb, __FUNCTION__,
+                       ext4_warning(sb, __func__,
                                     "Error opening resize inode");
                        return PTR_ERR(inode);
                }
@@ -810,7 +808,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
 
        lock_super(sb);
        if (input->group != sbi->s_groups_count) {
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "multiple resizers run on filesystem!");
                err = -EBUSY;
                goto exit_journal;
@@ -877,8 +875,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input)
         */
        ext4_blocks_count_set(es, ext4_blocks_count(es) +
                input->blocks_count);
-       es->s_inodes_count = cpu_to_le32(le32_to_cpu(es->s_inodes_count) +
-               EXT4_INODES_PER_GROUP(sb));
+       le32_add_cpu(&es->s_inodes_count, EXT4_INODES_PER_GROUP(sb));
 
        /*
         * We need to protect s_groups_count against other CPUs seeing
@@ -977,13 +974,13 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
                        " too large to resize to %llu blocks safely\n",
                        sb->s_id, n_blocks_count);
                if (sizeof(sector_t) < 8)
-                       ext4_warning(sb, __FUNCTION__,
+                       ext4_warning(sb, __func__,
                        "CONFIG_LBD not enabled\n");
                return -EINVAL;
        }
 
        if (n_blocks_count < o_blocks_count) {
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "can't shrink FS - resize aborted");
                return -EBUSY;
        }
@@ -992,7 +989,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
        ext4_get_group_no_and_offset(sb, o_blocks_count, NULL, &last);
 
        if (last == 0) {
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "need to use ext2online to resize further");
                return -EPERM;
        }
@@ -1000,7 +997,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
        add = EXT4_BLOCKS_PER_GROUP(sb) - last;
 
        if (o_blocks_count + add < o_blocks_count) {
-               ext4_warning(sb, __FUNCTION__, "blocks_count overflow");
+               ext4_warning(sb, __func__, "blocks_count overflow");
                return -EINVAL;
        }
 
@@ -1008,7 +1005,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
                add = n_blocks_count - o_blocks_count;
 
        if (o_blocks_count + add < n_blocks_count)
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "will only finish group (%llu"
                             " blocks, %u new)",
                             o_blocks_count + add, add);
@@ -1016,7 +1013,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
        /* See if the device is actually as big as what was requested */
        bh = sb_bread(sb, o_blocks_count + add -1);
        if (!bh) {
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "can't read last block, resize aborted");
                return -ENOSPC;
        }
@@ -1028,13 +1025,13 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
        handle = ext4_journal_start_sb(sb, 3);
        if (IS_ERR(handle)) {
                err = PTR_ERR(handle);
-               ext4_warning(sb, __FUNCTION__, "error %d on journal start",err);
+               ext4_warning(sb, __func__, "error %d on journal start", err);
                goto exit_put;
        }
 
        lock_super(sb);
        if (o_blocks_count != ext4_blocks_count(es)) {
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "multiple resizers run on filesystem!");
                unlock_super(sb);
                ext4_journal_stop(handle);
@@ -1044,7 +1041,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es,
 
        if ((err = ext4_journal_get_write_access(handle,
                                                 EXT4_SB(sb)->s_sbh))) {
-               ext4_warning(sb, __FUNCTION__,
+               ext4_warning(sb, __func__,
                             "error %d on journal write access", err);
                unlock_super(sb);
                ext4_journal_stop(handle);
index c81a8e759bad445b642feeeaca374383169d2b52..52dd0679a4e2f8d77e418cb1f6bd5a842bc10ca1 100644 (file)
@@ -21,8 +21,6 @@
 #include <linux/fs.h>
 #include <linux/time.h>
 #include <linux/jbd2.h>
-#include <linux/ext4_fs.h>
-#include <linux/ext4_jbd2.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/seq_file.h>
 #include <linux/log2.h>
 #include <linux/crc16.h>
-
 #include <asm/uaccess.h>
 
+#include "ext4.h"
+#include "ext4_jbd2.h"
 #include "xattr.h"
 #include "acl.h"
 #include "namei.h"
@@ -135,7 +134,7 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
         * take the FS itself readonly cleanly. */
        journal = EXT4_SB(sb)->s_journal;
        if (is_journal_aborted(journal)) {
-               ext4_abort(sb, __FUNCTION__,
+               ext4_abort(sb, __func__,
                           "Detected aborted journal");
                return ERR_PTR(-EROFS);
        }
@@ -355,7 +354,7 @@ void ext4_update_dynamic_rev(struct super_block *sb)
        if (le32_to_cpu(es->s_rev_level) > EXT4_GOOD_OLD_REV)
                return;
 
-       ext4_warning(sb, __FUNCTION__,
+       ext4_warning(sb, __func__,
                     "updating to rev %d because of new feature flag, "
                     "running e2fsck is recommended",
                     EXT4_DYNAMIC_REV);
@@ -945,8 +944,8 @@ static match_table_t tokens = {
        {Opt_mballoc, "mballoc"},
        {Opt_nomballoc, "nomballoc"},
        {Opt_stripe, "stripe=%u"},
-       {Opt_err, NULL},
        {Opt_resize, "resize"},
+       {Opt_err, NULL},
 };
 
 static ext4_fsblk_t get_sb_block(void **data)
@@ -1388,11 +1387,11 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
                 * a plain journaled filesystem we can keep it set as
                 * valid forever! :)
                 */
-       es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~EXT4_VALID_FS);
+       es->s_state &= cpu_to_le16(~EXT4_VALID_FS);
 #endif
        if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
                es->s_max_mnt_count = cpu_to_le16(EXT4_DFL_MAX_MNT_COUNT);
-       es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1);
+       le16_add_cpu(&es->s_mnt_count, 1);
        es->s_mtime = cpu_to_le32(get_seconds());
        ext4_update_dynamic_rev(sb);
        EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
@@ -1485,36 +1484,33 @@ static int ext4_check_descriptors(struct super_block *sb)
                block_bitmap = ext4_block_bitmap(sb, gdp);
                if (block_bitmap < first_block || block_bitmap > last_block)
                {
-                       ext4_error (sb, "ext4_check_descriptors",
-                                   "Block bitmap for group %lu"
-                                   " not in group (block %llu)!",
-                                   i, block_bitmap);
+                       printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
+                              "Block bitmap for group %lu not in group "
+                              "(block %llu)!", i, block_bitmap);
                        return 0;
                }
                inode_bitmap = ext4_inode_bitmap(sb, gdp);
                if (inode_bitmap < first_block || inode_bitmap > last_block)
                {
-                       ext4_error (sb, "ext4_check_descriptors",
-                                   "Inode bitmap for group %lu"
-                                   " not in group (block %llu)!",
-                                   i, inode_bitmap);
+                       printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
+                              "Inode bitmap for group %lu not in group "
+                              "(block %llu)!", i, inode_bitmap);
                        return 0;
                }
                inode_table = ext4_inode_table(sb, gdp);
                if (inode_table < first_block ||
                    inode_table + sbi->s_itb_per_group - 1 > last_block)
                {
-                       ext4_error (sb, "ext4_check_descriptors",
-                                   "Inode table for group %lu"
-                                   " not in group (block %llu)!",
-                                   i, inode_table);
+                       printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
+                              "Inode table for group %lu not in group "
+                              "(block %llu)!", i, inode_table);
                        return 0;
                }
                if (!ext4_group_desc_csum_verify(sbi, i, gdp)) {
-                       ext4_error(sb, __FUNCTION__,
-                                  "Checksum for group %lu failed (%u!=%u)\n",
-                                   i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
-                                   gdp)), le16_to_cpu(gdp->bg_checksum));
+                       printk(KERN_ERR "EXT4-fs: ext4_check_descriptors: "
+                              "Checksum for group %lu failed (%u!=%u)\n",
+                              i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
+                              gdp)), le16_to_cpu(gdp->bg_checksum));
                        return 0;
                }
                if (!flexbg_flag)
@@ -1594,8 +1590,8 @@ static void ext4_orphan_cleanup (struct super_block * sb,
        while (es->s_last_orphan) {
                struct inode *inode;
 
-               if (!(inode =
-                     ext4_orphan_get(sb, le32_to_cpu(es->s_last_orphan)))) {
+               inode = ext4_orphan_get(sb, le32_to_cpu(es->s_last_orphan));
+               if (IS_ERR(inode)) {
                        es->s_last_orphan = 0;
                        break;
                }
@@ -1605,7 +1601,7 @@ static void ext4_orphan_cleanup (struct super_block * sb,
                if (inode->i_nlink) {
                        printk(KERN_DEBUG
                                "%s: truncating inode %lu to %Ld bytes\n",
-                               __FUNCTION__, inode->i_ino, inode->i_size);
+                               __func__, inode->i_ino, inode->i_size);
                        jbd_debug(2, "truncating inode %lu to %Ld bytes\n",
                                  inode->i_ino, inode->i_size);
                        ext4_truncate(inode);
@@ -1613,7 +1609,7 @@ static void ext4_orphan_cleanup (struct super_block * sb,
                } else {
                        printk(KERN_DEBUG
                                "%s: deleting unreferenced inode %lu\n",
-                               __FUNCTION__, inode->i_ino);
+                               __func__, inode->i_ino);
                        jbd_debug(2, "deleting unreferenced inode %lu\n",
                                  inode->i_ino);
                        nr_orphans++;
@@ -2699,9 +2695,9 @@ static void ext4_clear_journal_err(struct super_block * sb,
                char nbuf[16];
 
                errstr = ext4_decode_error(sb, j_errno, nbuf);
-               ext4_warning(sb, __FUNCTION__, "Filesystem error recorded "
+               ext4_warning(sb, __func__, "Filesystem error recorded "
                             "from previous mount: %s", errstr);
-               ext4_warning(sb, __FUNCTION__, "Marking fs in need of "
+               ext4_warning(sb, __func__, "Marking fs in need of "
                             "filesystem check.");
 
                EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
@@ -2828,7 +2824,7 @@ static int ext4_remount (struct super_block * sb, int * flags, char * data)
        }
 
        if (sbi->s_mount_opt & EXT4_MOUNT_ABORT)
-               ext4_abort(sb, __FUNCTION__, "Abort forced by user");
+               ext4_abort(sb, __func__, "Abort forced by user");
 
        sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
                ((sbi->s_mount_opt & EXT4_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
@@ -3040,8 +3036,14 @@ static int ext4_dquot_drop(struct inode *inode)
 
        /* We may delete quota structure so we need to reserve enough blocks */
        handle = ext4_journal_start(inode, 2*EXT4_QUOTA_DEL_BLOCKS(inode->i_sb));
-       if (IS_ERR(handle))
+       if (IS_ERR(handle)) {
+               /*
+                * We call dquot_drop() anyway to at least release references
+                * to quota structures so that umount does not hang.
+                */
+               dquot_drop(inode);
                return PTR_ERR(handle);
+       }
        ret = dquot_drop(inode);
        err = ext4_journal_stop(handle);
        if (!ret)
index e6f9da4287c455d5975a87668d90dff7e1dcd766..e9178643dc01132b72a396b8099ad0cd8c3785c6 100644 (file)
@@ -19,8 +19,8 @@
 
 #include <linux/fs.h>
 #include <linux/jbd2.h>
-#include <linux/ext4_fs.h>
 #include <linux/namei.h>
+#include "ext4.h"
 #include "xattr.h"
 
 static void * ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
index e9054c1c7d9366ce36f1d140b125c5db8915cd15..3fbc2c6c3d0e900c5ce8e1a5f8e56270f5984768 100644 (file)
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
-#include <linux/ext4_jbd2.h>
-#include <linux/ext4_fs.h>
 #include <linux/mbcache.h>
 #include <linux/quotaops.h>
 #include <linux/rwsem.h>
+#include "ext4_jbd2.h"
+#include "ext4.h"
 #include "xattr.h"
 #include "acl.h"
 
@@ -92,6 +92,8 @@ static struct buffer_head *ext4_xattr_cache_find(struct inode *,
                                                 struct mb_cache_entry **);
 static void ext4_xattr_rehash(struct ext4_xattr_header *,
                              struct ext4_xattr_entry *);
+static int ext4_xattr_list(struct inode *inode, char *buffer,
+                          size_t buffer_size);
 
 static struct mb_cache *ext4_xattr_cache;
 
@@ -225,7 +227,7 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
        ea_bdebug(bh, "b_count=%d, refcount=%d",
                atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
        if (ext4_xattr_check_block(bh)) {
-bad_block:     ext4_error(inode->i_sb, __FUNCTION__,
+bad_block:     ext4_error(inode->i_sb, __func__,
                           "inode %lu: bad block %llu", inode->i_ino,
                           EXT4_I(inode)->i_file_acl);
                error = -EIO;
@@ -367,7 +369,7 @@ ext4_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
        ea_bdebug(bh, "b_count=%d, refcount=%d",
                atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
        if (ext4_xattr_check_block(bh)) {
-               ext4_error(inode->i_sb, __FUNCTION__,
+               ext4_error(inode->i_sb, __func__,
                           "inode %lu: bad block %llu", inode->i_ino,
                           EXT4_I(inode)->i_file_acl);
                error = -EIO;
@@ -420,7 +422,7 @@ cleanup:
  * Returns a negative error number on failure, or the number of bytes
  * used / required on success.
  */
-int
+static int
 ext4_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
 {
        int i_error, b_error;
@@ -484,8 +486,7 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
                get_bh(bh);
                ext4_forget(handle, 1, inode, bh, bh->b_blocknr);
        } else {
-               BHDR(bh)->h_refcount = cpu_to_le32(
-                               le32_to_cpu(BHDR(bh)->h_refcount) - 1);
+               le32_add_cpu(&BHDR(bh)->h_refcount, -1);
                error = ext4_journal_dirty_metadata(handle, bh);
                if (IS_SYNC(inode))
                        handle->h_sync = 1;
@@ -660,7 +661,7 @@ ext4_xattr_block_find(struct inode *inode, struct ext4_xattr_info *i,
                        atomic_read(&(bs->bh->b_count)),
                        le32_to_cpu(BHDR(bs->bh)->h_refcount));
                if (ext4_xattr_check_block(bs->bh)) {
-                       ext4_error(sb, __FUNCTION__,
+                       ext4_error(sb, __func__,
                                "inode %lu: bad block %llu", inode->i_ino,
                                EXT4_I(inode)->i_file_acl);
                        error = -EIO;
@@ -738,7 +739,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
                                ce = NULL;
                        }
                        ea_bdebug(bs->bh, "cloning");
-                       s->base = kmalloc(bs->bh->b_size, GFP_KERNEL);
+                       s->base = kmalloc(bs->bh->b_size, GFP_NOFS);
                        error = -ENOMEM;
                        if (s->base == NULL)
                                goto cleanup;
@@ -750,7 +751,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
                }
        } else {
                /* Allocate a buffer where we construct the new block. */
-               s->base = kzalloc(sb->s_blocksize, GFP_KERNEL);
+               s->base = kzalloc(sb->s_blocksize, GFP_NOFS);
                /* assert(header == s->base) */
                error = -ENOMEM;
                if (s->base == NULL)
@@ -789,8 +790,7 @@ inserted:
                                if (error)
                                        goto cleanup_dquot;
                                lock_buffer(new_bh);
-                               BHDR(new_bh)->h_refcount = cpu_to_le32(1 +
-                                       le32_to_cpu(BHDR(new_bh)->h_refcount));
+                               le32_add_cpu(&BHDR(new_bh)->h_refcount, 1);
                                ea_bdebug(new_bh, "reusing; refcount now=%d",
                                        le32_to_cpu(BHDR(new_bh)->h_refcount));
                                unlock_buffer(new_bh);
@@ -808,10 +808,8 @@ inserted:
                        get_bh(new_bh);
                } else {
                        /* We need to allocate a new block */
-                       ext4_fsblk_t goal = le32_to_cpu(
-                                       EXT4_SB(sb)->s_es->s_first_data_block) +
-                               (ext4_fsblk_t)EXT4_I(inode)->i_block_group *
-                               EXT4_BLOCKS_PER_GROUP(sb);
+                       ext4_fsblk_t goal = ext4_group_first_block_no(sb,
+                                               EXT4_I(inode)->i_block_group);
                        ext4_fsblk_t block = ext4_new_block(handle, inode,
                                                        goal, &error);
                        if (error)
@@ -863,7 +861,7 @@ cleanup_dquot:
        goto cleanup;
 
 bad_block:
-       ext4_error(inode->i_sb, __FUNCTION__,
+       ext4_error(inode->i_sb, __func__,
                   "inode %lu: bad block %llu", inode->i_ino,
                   EXT4_I(inode)->i_file_acl);
        goto cleanup;
@@ -1166,7 +1164,7 @@ retry:
                if (!bh)
                        goto cleanup;
                if (ext4_xattr_check_block(bh)) {
-                       ext4_error(inode->i_sb, __FUNCTION__,
+                       ext4_error(inode->i_sb, __func__,
                                "inode %lu: bad block %llu", inode->i_ino,
                                EXT4_I(inode)->i_file_acl);
                        error = -EIO;
@@ -1341,14 +1339,14 @@ ext4_xattr_delete_inode(handle_t *handle, struct inode *inode)
                goto cleanup;
        bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
        if (!bh) {
-               ext4_error(inode->i_sb, __FUNCTION__,
+               ext4_error(inode->i_sb, __func__,
                        "inode %lu: block %llu read error", inode->i_ino,
                        EXT4_I(inode)->i_file_acl);
                goto cleanup;
        }
        if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
            BHDR(bh)->h_blocks != cpu_to_le32(1)) {
-               ext4_error(inode->i_sb, __FUNCTION__,
+               ext4_error(inode->i_sb, __func__,
                        "inode %lu: bad block %llu", inode->i_ino,
                        EXT4_I(inode)->i_file_acl);
                goto cleanup;
@@ -1475,7 +1473,7 @@ again:
                }
                bh = sb_bread(inode->i_sb, ce->e_block);
                if (!bh) {
-                       ext4_error(inode->i_sb, __FUNCTION__,
+                       ext4_error(inode->i_sb, __func__,
                                "inode %lu: block %lu read error",
                                inode->i_ino, (unsigned long) ce->e_block);
                } else if (le32_to_cpu(BHDR(bh)->h_refcount) >=
index d7f5d6a126511e7f65c63793512732d6e31813bb..5992fe979bb960e4eda701b4c5f422d1fcb51148 100644 (file)
@@ -74,7 +74,6 @@ extern struct xattr_handler ext4_xattr_security_handler;
 extern ssize_t ext4_listxattr(struct dentry *, char *, size_t);
 
 extern int ext4_xattr_get(struct inode *, int, const char *, void *, size_t);
-extern int ext4_xattr_list(struct inode *, char *, size_t);
 extern int ext4_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
 extern int ext4_xattr_set_handle(handle_t *, struct inode *, int, const char *, const void *, size_t, int);
 
@@ -98,12 +97,6 @@ ext4_xattr_get(struct inode *inode, int name_index, const char *name,
        return -EOPNOTSUPP;
 }
 
-static inline int
-ext4_xattr_list(struct inode *inode, void *buffer, size_t size)
-{
-       return -EOPNOTSUPP;
-}
-
 static inline int
 ext4_xattr_set(struct inode *inode, int name_index, const char *name,
               const void *value, size_t size, int flags)
index f17eaf2321b9da564b303b5abfdccc0e2ff11018..ca5f89fc6caeba31ee41a15a3843452a1c0f56c6 100644 (file)
@@ -6,9 +6,9 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/fs.h>
-#include <linux/ext4_jbd2.h>
-#include <linux/ext4_fs.h>
 #include <linux/security.h>
+#include "ext4_jbd2.h"
+#include "ext4.h"
 #include "xattr.h"
 
 static size_t
index e0f05acdafece0e0826c2985fc0a59c556fa5159..fff33382cadcfc2b93d3e81dab1ad84e57364d6a 100644 (file)
@@ -9,8 +9,8 @@
 #include <linux/string.h>
 #include <linux/capability.h>
 #include <linux/fs.h>
-#include <linux/ext4_jbd2.h>
-#include <linux/ext4_fs.h>
+#include "ext4_jbd2.h"
+#include "ext4.h"
 #include "xattr.h"
 
 #define XATTR_TRUSTED_PREFIX "trusted."
index 7ed3d8ebf09686d2315e3a1ebdc92ccff5ada1ad..67be723fcc4eeb6cfa3cb996d5e029176b900cc7 100644 (file)
@@ -8,8 +8,8 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/fs.h>
-#include <linux/ext4_jbd2.h>
-#include <linux/ext4_fs.h>
+#include "ext4_jbd2.h"
+#include "ext4.h"
 #include "xattr.h"
 
 #define XATTR_USER_PREFIX "user."
index 639b3b4f86d15a8a17a331a3fabdbb16d0bc8048..fda25479af26720690969dde01f444d8bc730f07 100644 (file)
@@ -242,7 +242,7 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
                /* prevent the infinite loop of cluster chain */
                if (*fclus > limit) {
                        fat_fs_panic(sb, "%s: detected the cluster chain loop"
-                                    " (i_pos %lld)", __FUNCTION__,
+                                    " (i_pos %lld)", __func__,
                                     MSDOS_I(inode)->i_pos);
                        nr = -EIO;
                        goto out;
@@ -253,7 +253,7 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
                        goto out;
                else if (nr == FAT_ENT_FREE) {
                        fat_fs_panic(sb, "%s: invalid cluster chain"
-                                    " (i_pos %lld)", __FUNCTION__,
+                                    " (i_pos %lld)", __func__,
                                     MSDOS_I(inode)->i_pos);
                        nr = -EIO;
                        goto out;
@@ -286,7 +286,7 @@ static int fat_bmap_cluster(struct inode *inode, int cluster)
                return ret;
        else if (ret == FAT_ENT_EOF) {
                fat_fs_panic(sb, "%s: request beyond EOF (i_pos %lld)",
-                            __FUNCTION__, MSDOS_I(inode)->i_pos);
+                            __func__, MSDOS_I(inode)->i_pos);
                return -EIO;
        }
        return dclus;
index 13ab763cc5109addcb1b79448e37826a58cdf795..302e95c4af7e0c517704d987932411066c129d86 100644 (file)
@@ -546,7 +546,7 @@ int fat_free_clusters(struct inode *inode, int cluster)
                        goto error;
                } else if (cluster == FAT_ENT_FREE) {
                        fat_fs_panic(sb, "%s: deleting FAT entry beyond EOF",
-                                    __FUNCTION__);
+                                    __func__);
                        err = -EIO;
                        goto error;
                }
index d604bb132422450ccce7248df845b455721b6aa0..27cc1164ec36baa84284836686d1603a36451423 100644 (file)
@@ -208,7 +208,7 @@ static int fat_free(struct inode *inode, int skip)
                } else if (ret == FAT_ENT_FREE) {
                        fat_fs_panic(sb,
                                     "%s: invalid cluster chain (i_pos %lld)",
-                                    __FUNCTION__, MSDOS_I(inode)->i_pos);
+                                    __func__, MSDOS_I(inode)->i_pos);
                        ret = -EIO;
                } else if (ret > 0) {
                        err = fat_ent_write(inode, &fatent, FAT_ENT_EOF, wait);
index 5f522a55b596e32cfe440ae187f78891c8948f70..4e0a3dd9d6779a1d9101704d470b1263b194d7d5 100644 (file)
@@ -1222,8 +1222,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
                brelse(bh);
                goto out_invalid;
        }
-       logical_sector_size =
-               le16_to_cpu(get_unaligned((__le16 *)&b->sector_size));
+       logical_sector_size = get_unaligned_le16(&b->sector_size);
        if (!is_power_of_2(logical_sector_size)
            || (logical_sector_size < 512)
            || (logical_sector_size > 4096)) {
@@ -1322,8 +1321,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
        sbi->dir_per_block_bits = ffs(sbi->dir_per_block) - 1;
 
        sbi->dir_start = sbi->fat_start + sbi->fats * sbi->fat_length;
-       sbi->dir_entries =
-               le16_to_cpu(get_unaligned((__le16 *)&b->dir_entries));
+       sbi->dir_entries = get_unaligned_le16(&b->dir_entries);
        if (sbi->dir_entries & (sbi->dir_per_block - 1)) {
                if (!silent)
                        printk(KERN_ERR "FAT: bogus directroy-entries per block"
@@ -1335,7 +1333,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
        rootdir_sectors = sbi->dir_entries
                * sizeof(struct msdos_dir_entry) / sb->s_blocksize;
        sbi->data_start = sbi->dir_start + rootdir_sectors;
-       total_sectors = le16_to_cpu(get_unaligned((__le16 *)&b->sectors));
+       total_sectors = get_unaligned_le16(&b->sectors);
        if (total_sectors == 0)
                total_sectors = le32_to_cpu(b->total_sect);
 
index 2b46064f66b2ed1a393ef9729253f59d90115c06..50ab5eecb99b845d5c88b81e83fdfeaa0eafaa2e 100644 (file)
@@ -50,7 +50,11 @@ extern daddr_t                       vxfs_bmap1(struct inode *, long);
 /* vxfs_fshead.c */
 extern int                     vxfs_read_fshead(struct super_block *);
 
+/* vxfs_immed.c */
+extern const struct inode_operations vxfs_immed_symlink_iops;
+
 /* vxfs_inode.c */
+extern const struct address_space_operations vxfs_immed_aops;
 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 *,
@@ -69,6 +73,7 @@ extern const struct file_operations   vxfs_dir_operations;
 extern int                     vxfs_read_olt(struct super_block *, u_long);
 
 /* vxfs_subr.c */
+extern const struct address_space_operations vxfs_aops;
 extern struct page *           vxfs_get_page(struct address_space *, u_long);
 extern void                    vxfs_put_page(struct page *);
 extern struct buffer_head *    vxfs_bread(struct inode *, int);
index 8a5959a61ba9dbff4b9b713efa1f5d42da003e1f..c36aeaf92e41070cb905d57ffb1b6df8ce2dac4d 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/namei.h>
 
 #include "vxfs.h"
+#include "vxfs_extern.h"
 #include "vxfs_inode.h"
 
 
index ad88d2364bc258bc2d1b07283304d935eeab3369..9f3f2ceb73f00743f0869e086a2e3cb557065748 100644 (file)
 #include "vxfs_extern.h"
 
 
-extern const struct address_space_operations vxfs_aops;
-extern const struct address_space_operations vxfs_immed_aops;
-
-extern const struct inode_operations vxfs_immed_symlink_iops;
-
 struct kmem_cache              *vxfs_inode_cachep;
 
 
index 06557679ca411d6fbce09a33dddd042f938ecbc2..ae45f77765c0ee65a647fc81c899315de2f0862f 100644 (file)
 #include <linux/buffer_head.h>
 #include "internal.h"
 
+
+/**
+ * writeback_acquire - attempt to get exclusive writeback access to a device
+ * @bdi: the device's backing_dev_info structure
+ *
+ * It is a waste of resources to have more than one pdflush thread blocked on
+ * a single request queue.  Exclusion at the request_queue level is obtained
+ * via a flag in the request_queue's backing_dev_info.state.
+ *
+ * Non-request_queue-backed address_spaces will share default_backing_dev_info,
+ * unless they implement their own.  Which is somewhat inefficient, as this
+ * may prevent concurrent writeback against multiple devices.
+ */
+static int writeback_acquire(struct backing_dev_info *bdi)
+{
+       return !test_and_set_bit(BDI_pdflush, &bdi->state);
+}
+
+/**
+ * writeback_in_progress - determine whether there is writeback in progress
+ * @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)
+{
+       return test_bit(BDI_pdflush, &bdi->state);
+}
+
+/**
+ * writeback_release - relinquish exclusive writeback access against a device.
+ * @bdi: the device's backing_dev_info structure
+ */
+static void writeback_release(struct backing_dev_info *bdi)
+{
+       BUG_ON(!writeback_in_progress(bdi));
+       clear_bit(BDI_pdflush, &bdi->state);
+}
+
 /**
  *     __mark_inode_dirty -    internal function
  *     @inode: inode to mark
@@ -747,43 +786,4 @@ int generic_osync_inode(struct inode *inode, struct address_space *mapping, int
 
        return err;
 }
-
 EXPORT_SYMBOL(generic_osync_inode);
-
-/**
- * writeback_acquire - attempt to get exclusive writeback access to a device
- * @bdi: the device's backing_dev_info structure
- *
- * It is a waste of resources to have more than one pdflush thread blocked on
- * a single request queue.  Exclusion at the request_queue level is obtained
- * via a flag in the request_queue's backing_dev_info.state.
- *
- * Non-request_queue-backed address_spaces will share default_backing_dev_info,
- * unless they implement their own.  Which is somewhat inefficient, as this
- * may prevent concurrent writeback against multiple devices.
- */
-int writeback_acquire(struct backing_dev_info *bdi)
-{
-       return !test_and_set_bit(BDI_pdflush, &bdi->state);
-}
-
-/**
- * writeback_in_progress - determine whether there is writeback in progress
- * @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)
-{
-       return test_bit(BDI_pdflush, &bdi->state);
-}
-
-/**
- * writeback_release - relinquish exclusive writeback access against a device.
- * @bdi: the device's backing_dev_info structure
- */
-void writeback_release(struct backing_dev_info *bdi)
-{
-       BUG_ON(!writeback_in_progress(bdi));
-       clear_bit(BDI_pdflush, &bdi->state);
-}
index 105d4a271e073b0c7d60660057d9716d798f9d1d..4f3cab32141584264789ab3446f962d631ba04ab 100644 (file)
@@ -117,7 +117,7 @@ int fuse_ctl_add_conn(struct fuse_conn *fc)
 
        parent = fuse_control_sb->s_root;
        inc_nlink(parent->d_inode);
-       sprintf(name, "%llu", (unsigned long long) fc->id);
+       sprintf(name, "%u", fc->dev);
        parent = fuse_ctl_add_dentry(parent, fc, name, S_IFDIR | 0500, 2,
                                     &simple_dir_inode_operations,
                                     &simple_dir_operations);
index af639807524e63164397b32f8589bf75131a5112..87250b6a8682468c39ff0e4cb1f35caa09f386f6 100644 (file)
@@ -47,6 +47,14 @@ struct fuse_req *fuse_request_alloc(void)
        return req;
 }
 
+struct fuse_req *fuse_request_alloc_nofs(void)
+{
+       struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, GFP_NOFS);
+       if (req)
+               fuse_request_init(req);
+       return req;
+}
+
 void fuse_request_free(struct fuse_req *req)
 {
        kmem_cache_free(fuse_req_cachep, req);
@@ -291,6 +299,7 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
 
 static void wait_answer_interruptible(struct fuse_conn *fc,
                                      struct fuse_req *req)
+       __releases(fc->lock) __acquires(fc->lock)
 {
        if (signal_pending(current))
                return;
@@ -307,8 +316,8 @@ static void queue_interrupt(struct fuse_conn *fc, struct fuse_req *req)
        kill_fasync(&fc->fasync, SIGIO, POLL_IN);
 }
 
-/* Called with fc->lock held.  Releases, and then reacquires it. */
 static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
+       __releases(fc->lock) __acquires(fc->lock)
 {
        if (!fc->no_interrupt) {
                /* Any signal may interrupt this */
@@ -429,6 +438,17 @@ void request_send_background(struct fuse_conn *fc, struct fuse_req *req)
        request_send_nowait(fc, req);
 }
 
+/*
+ * Called under fc->lock
+ *
+ * fc->connected must have been checked previously
+ */
+void request_send_background_locked(struct fuse_conn *fc, struct fuse_req *req)
+{
+       req->isreply = 1;
+       request_send_nowait_locked(fc, req);
+}
+
 /*
  * Lock the request.  Up to the next unlock_request() there mustn't be
  * anything that could cause a page-fault.  If the request was already
@@ -968,6 +988,7 @@ static void end_requests(struct fuse_conn *fc, struct list_head *head)
  * locked).
  */
 static void end_io_requests(struct fuse_conn *fc)
+       __releases(fc->lock) __acquires(fc->lock)
 {
        while (!list_empty(&fc->io)) {
                struct fuse_req *req =
index c4807b3fc8a360776bda6f976baebd26b5c9ae92..2060bf06b90625cf920aa08f87da07bd286a193f 100644 (file)
@@ -132,7 +132,7 @@ static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
        req->out.args[0].value = outarg;
 }
 
-static u64 fuse_get_attr_version(struct fuse_conn *fc)
+u64 fuse_get_attr_version(struct fuse_conn *fc)
 {
        u64 curr_version;
 
@@ -1106,6 +1106,50 @@ static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
        }
 }
 
+/*
+ * Prevent concurrent writepages on inode
+ *
+ * This is done by adding a negative bias to the inode write counter
+ * and waiting for all pending writes to finish.
+ */
+void fuse_set_nowrite(struct inode *inode)
+{
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_inode *fi = get_fuse_inode(inode);
+
+       BUG_ON(!mutex_is_locked(&inode->i_mutex));
+
+       spin_lock(&fc->lock);
+       BUG_ON(fi->writectr < 0);
+       fi->writectr += FUSE_NOWRITE;
+       spin_unlock(&fc->lock);
+       wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
+}
+
+/*
+ * Allow writepages on inode
+ *
+ * Remove the bias from the writecounter and send any queued
+ * writepages.
+ */
+static void __fuse_release_nowrite(struct inode *inode)
+{
+       struct fuse_inode *fi = get_fuse_inode(inode);
+
+       BUG_ON(fi->writectr != FUSE_NOWRITE);
+       fi->writectr = 0;
+       fuse_flush_writepages(inode);
+}
+
+void fuse_release_nowrite(struct inode *inode)
+{
+       struct fuse_conn *fc = get_fuse_conn(inode);
+
+       spin_lock(&fc->lock);
+       __fuse_release_nowrite(inode);
+       spin_unlock(&fc->lock);
+}
+
 /*
  * Set attributes, and at the same time refresh them.
  *
@@ -1122,6 +1166,8 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
        struct fuse_req *req;
        struct fuse_setattr_in inarg;
        struct fuse_attr_out outarg;
+       bool is_truncate = false;
+       loff_t oldsize;
        int err;
 
        if (!fuse_allow_task(fc, current))
@@ -1145,12 +1191,16 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
                        send_sig(SIGXFSZ, current, 0);
                        return -EFBIG;
                }
+               is_truncate = true;
        }
 
        req = fuse_get_req(fc);
        if (IS_ERR(req))
                return PTR_ERR(req);
 
+       if (is_truncate)
+               fuse_set_nowrite(inode);
+
        memset(&inarg, 0, sizeof(inarg));
        memset(&outarg, 0, sizeof(outarg));
        iattr_to_fattr(attr, &inarg);
@@ -1181,16 +1231,44 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
        if (err) {
                if (err == -EINTR)
                        fuse_invalidate_attr(inode);
-               return err;
+               goto error;
        }
 
        if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
                make_bad_inode(inode);
-               return -EIO;
+               err = -EIO;
+               goto error;
+       }
+
+       spin_lock(&fc->lock);
+       fuse_change_attributes_common(inode, &outarg.attr,
+                                     attr_timeout(&outarg));
+       oldsize = inode->i_size;
+       i_size_write(inode, outarg.attr.size);
+
+       if (is_truncate) {
+               /* NOTE: this may release/reacquire fc->lock */
+               __fuse_release_nowrite(inode);
+       }
+       spin_unlock(&fc->lock);
+
+       /*
+        * Only call invalidate_inode_pages2() after removing
+        * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
+        */
+       if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
+               if (outarg.attr.size < oldsize)
+                       fuse_truncate(inode->i_mapping, outarg.attr.size);
+               invalidate_inode_pages2(inode->i_mapping);
        }
 
-       fuse_change_attributes(inode, &outarg.attr, attr_timeout(&outarg), 0);
        return 0;
+
+error:
+       if (is_truncate)
+               fuse_release_nowrite(inode);
+
+       return err;
 }
 
 static int fuse_setattr(struct dentry *entry, struct iattr *attr)
index 676b0bc8a86dba3e3c048a1a35320d3931a65f20..9ced35b006867e1445af3f9fe010906ac0684f87 100644 (file)
@@ -210,6 +210,49 @@ u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
        return (u64) v0 + ((u64) v1 << 32);
 }
 
+/*
+ * Check if page is under writeback
+ *
+ * This is currently done by walking the list of writepage requests
+ * for the inode, which can be pretty inefficient.
+ */
+static bool fuse_page_is_writeback(struct inode *inode, pgoff_t index)
+{
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_inode *fi = get_fuse_inode(inode);
+       struct fuse_req *req;
+       bool found = false;
+
+       spin_lock(&fc->lock);
+       list_for_each_entry(req, &fi->writepages, writepages_entry) {
+               pgoff_t curr_index;
+
+               BUG_ON(req->inode != inode);
+               curr_index = req->misc.write.in.offset >> PAGE_CACHE_SHIFT;
+               if (curr_index == index) {
+                       found = true;
+                       break;
+               }
+       }
+       spin_unlock(&fc->lock);
+
+       return found;
+}
+
+/*
+ * Wait for page writeback to be completed.
+ *
+ * Since fuse doesn't rely on the VM writeback tracking, this has to
+ * use some other means.
+ */
+static int fuse_wait_on_page_writeback(struct inode *inode, pgoff_t index)
+{
+       struct fuse_inode *fi = get_fuse_inode(inode);
+
+       wait_event(fi->page_waitq, !fuse_page_is_writeback(inode, index));
+       return 0;
+}
+
 static int fuse_flush(struct file *file, fl_owner_t id)
 {
        struct inode *inode = file->f_path.dentry->d_inode;
@@ -245,6 +288,21 @@ static int fuse_flush(struct file *file, fl_owner_t id)
        return err;
 }
 
+/*
+ * Wait for all pending writepages on the inode to finish.
+ *
+ * This is currently done by blocking further writes with FUSE_NOWRITE
+ * and waiting for all sent writes to complete.
+ *
+ * This must be called under i_mutex, otherwise the FUSE_NOWRITE usage
+ * could conflict with truncation.
+ */
+static void fuse_sync_writes(struct inode *inode)
+{
+       fuse_set_nowrite(inode);
+       fuse_release_nowrite(inode);
+}
+
 int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
                      int isdir)
 {
@@ -261,6 +319,17 @@ int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
        if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
                return 0;
 
+       /*
+        * Start writeback against all dirty pages of the inode, then
+        * wait for all outstanding writes, before sending the FSYNC
+        * request.
+        */
+       err = write_inode_now(inode, 0);
+       if (err)
+               return err;
+
+       fuse_sync_writes(inode);
+
        req = fuse_get_req(fc);
        if (IS_ERR(req))
                return PTR_ERR(req);
@@ -294,7 +363,7 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
 void fuse_read_fill(struct fuse_req *req, struct file *file,
                    struct inode *inode, loff_t pos, size_t count, int opcode)
 {
-       struct fuse_read_in *inarg = &req->misc.read_in;
+       struct fuse_read_in *inarg = &req->misc.read.in;
        struct fuse_file *ff = file->private_data;
 
        inarg->fh = ff->fh;
@@ -320,7 +389,7 @@ static size_t fuse_send_read(struct fuse_req *req, struct file *file,
 
        fuse_read_fill(req, file, inode, pos, count, FUSE_READ);
        if (owner != NULL) {
-               struct fuse_read_in *inarg = &req->misc.read_in;
+               struct fuse_read_in *inarg = &req->misc.read.in;
 
                inarg->read_flags |= FUSE_READ_LOCKOWNER;
                inarg->lock_owner = fuse_lock_owner_id(fc, owner);
@@ -329,31 +398,66 @@ static size_t fuse_send_read(struct fuse_req *req, struct file *file,
        return req->out.args[0].size;
 }
 
+static void fuse_read_update_size(struct inode *inode, loff_t size,
+                                 u64 attr_ver)
+{
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_inode *fi = get_fuse_inode(inode);
+
+       spin_lock(&fc->lock);
+       if (attr_ver == fi->attr_version && size < inode->i_size) {
+               fi->attr_version = ++fc->attr_version;
+               i_size_write(inode, size);
+       }
+       spin_unlock(&fc->lock);
+}
+
 static int fuse_readpage(struct file *file, struct page *page)
 {
        struct inode *inode = page->mapping->host;
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_req *req;
+       size_t num_read;
+       loff_t pos = page_offset(page);
+       size_t count = PAGE_CACHE_SIZE;
+       u64 attr_ver;
        int err;
 
        err = -EIO;
        if (is_bad_inode(inode))
                goto out;
 
+       /*
+        * Page writeback can extend beyond the liftime of the
+        * page-cache page, so make sure we read a properly synced
+        * page.
+        */
+       fuse_wait_on_page_writeback(inode, page->index);
+
        req = fuse_get_req(fc);
        err = PTR_ERR(req);
        if (IS_ERR(req))
                goto out;
 
+       attr_ver = fuse_get_attr_version(fc);
+
        req->out.page_zeroing = 1;
        req->num_pages = 1;
        req->pages[0] = page;
-       fuse_send_read(req, file, inode, page_offset(page), PAGE_CACHE_SIZE,
-                      NULL);
+       num_read = fuse_send_read(req, file, inode, pos, count, NULL);
        err = req->out.h.error;
        fuse_put_request(fc, req);
-       if (!err)
+
+       if (!err) {
+               /*
+                * Short read means EOF.  If file size is larger, truncate it
+                */
+               if (num_read < count)
+                       fuse_read_update_size(inode, pos + num_read, attr_ver);
+
                SetPageUptodate(page);
+       }
+
        fuse_invalidate_attr(inode); /* atime changed */
  out:
        unlock_page(page);
@@ -363,8 +467,19 @@ static int fuse_readpage(struct file *file, struct page *page)
 static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req)
 {
        int i;
+       size_t count = req->misc.read.in.size;
+       size_t num_read = req->out.args[0].size;
+       struct inode *inode = req->pages[0]->mapping->host;
+
+       /*
+        * Short read means EOF.  If file size is larger, truncate it
+        */
+       if (!req->out.h.error && num_read < count) {
+               loff_t pos = page_offset(req->pages[0]) + num_read;
+               fuse_read_update_size(inode, pos, req->misc.read.attr_ver);
+       }
 
-       fuse_invalidate_attr(req->pages[0]->mapping->host); /* atime changed */
+       fuse_invalidate_attr(inode); /* atime changed */
 
        for (i = 0; i < req->num_pages; i++) {
                struct page *page = req->pages[i];
@@ -387,6 +502,7 @@ static void fuse_send_readpages(struct fuse_req *req, struct file *file,
        size_t count = req->num_pages << PAGE_CACHE_SHIFT;
        req->out.page_zeroing = 1;
        fuse_read_fill(req, file, inode, pos, count, FUSE_READ);
+       req->misc.read.attr_ver = fuse_get_attr_version(fc);
        if (fc->async_read) {
                struct fuse_file *ff = file->private_data;
                req->ff = fuse_file_get(ff);
@@ -411,6 +527,8 @@ static int fuse_readpages_fill(void *_data, struct page *page)
        struct inode *inode = data->inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
 
+       fuse_wait_on_page_writeback(inode, page->index);
+
        if (req->num_pages &&
            (req->num_pages == FUSE_MAX_PAGES_PER_REQ ||
             (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read ||
@@ -477,11 +595,10 @@ static ssize_t fuse_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
 }
 
 static void fuse_write_fill(struct fuse_req *req, struct file *file,
-                           struct inode *inode, loff_t pos, size_t count,
-                           int writepage)
+                           struct fuse_file *ff, struct inode *inode,
+                           loff_t pos, size_t count, int writepage)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
-       struct fuse_file *ff = file->private_data;
        struct fuse_write_in *inarg = &req->misc.write.in;
        struct fuse_write_out *outarg = &req->misc.write.out;
 
@@ -490,7 +607,7 @@ static void fuse_write_fill(struct fuse_req *req, struct file *file,
        inarg->offset = pos;
        inarg->size = count;
        inarg->write_flags = writepage ? FUSE_WRITE_CACHE : 0;
-       inarg->flags = file->f_flags;
+       inarg->flags = file ? file->f_flags : 0;
        req->in.h.opcode = FUSE_WRITE;
        req->in.h.nodeid = get_node_id(inode);
        req->in.argpages = 1;
@@ -511,7 +628,7 @@ static size_t fuse_send_write(struct fuse_req *req, struct file *file,
                              fl_owner_t owner)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
-       fuse_write_fill(req, file, inode, pos, count, 0);
+       fuse_write_fill(req, file, file->private_data, inode, pos, count, 0);
        if (owner != NULL) {
                struct fuse_write_in *inarg = &req->misc.write.in;
                inarg->write_flags |= FUSE_WRITE_LOCKOWNER;
@@ -533,19 +650,36 @@ static int fuse_write_begin(struct file *file, struct address_space *mapping,
        return 0;
 }
 
+static void fuse_write_update_size(struct inode *inode, loff_t pos)
+{
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_inode *fi = get_fuse_inode(inode);
+
+       spin_lock(&fc->lock);
+       fi->attr_version = ++fc->attr_version;
+       if (pos > inode->i_size)
+               i_size_write(inode, pos);
+       spin_unlock(&fc->lock);
+}
+
 static int fuse_buffered_write(struct file *file, struct inode *inode,
                               loff_t pos, unsigned count, struct page *page)
 {
        int err;
        size_t nres;
        struct fuse_conn *fc = get_fuse_conn(inode);
-       struct fuse_inode *fi = get_fuse_inode(inode);
        unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
        struct fuse_req *req;
 
        if (is_bad_inode(inode))
                return -EIO;
 
+       /*
+        * Make sure writepages on the same page are not mixed up with
+        * plain writes.
+        */
+       fuse_wait_on_page_writeback(inode, page->index);
+
        req = fuse_get_req(fc);
        if (IS_ERR(req))
                return PTR_ERR(req);
@@ -560,12 +694,7 @@ static int fuse_buffered_write(struct file *file, struct inode *inode,
                err = -EIO;
        if (!err) {
                pos += nres;
-               spin_lock(&fc->lock);
-               fi->attr_version = ++fc->attr_version;
-               if (pos > inode->i_size)
-                       i_size_write(inode, pos);
-               spin_unlock(&fc->lock);
-
+               fuse_write_update_size(inode, pos);
                if (count == PAGE_CACHE_SIZE)
                        SetPageUptodate(page);
        }
@@ -588,6 +717,198 @@ static int fuse_write_end(struct file *file, struct address_space *mapping,
        return res;
 }
 
+static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file,
+                                   struct inode *inode, loff_t pos,
+                                   size_t count)
+{
+       size_t res;
+       unsigned offset;
+       unsigned i;
+
+       for (i = 0; i < req->num_pages; i++)
+               fuse_wait_on_page_writeback(inode, req->pages[i]->index);
+
+       res = fuse_send_write(req, file, inode, pos, count, NULL);
+
+       offset = req->page_offset;
+       count = res;
+       for (i = 0; i < req->num_pages; i++) {
+               struct page *page = req->pages[i];
+
+               if (!req->out.h.error && !offset && count >= PAGE_CACHE_SIZE)
+                       SetPageUptodate(page);
+
+               if (count > PAGE_CACHE_SIZE - offset)
+                       count -= PAGE_CACHE_SIZE - offset;
+               else
+                       count = 0;
+               offset = 0;
+
+               unlock_page(page);
+               page_cache_release(page);
+       }
+
+       return res;
+}
+
+static ssize_t fuse_fill_write_pages(struct fuse_req *req,
+                              struct address_space *mapping,
+                              struct iov_iter *ii, loff_t pos)
+{
+       struct fuse_conn *fc = get_fuse_conn(mapping->host);
+       unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
+       size_t count = 0;
+       int err;
+
+       req->page_offset = offset;
+
+       do {
+               size_t tmp;
+               struct page *page;
+               pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+               size_t bytes = min_t(size_t, PAGE_CACHE_SIZE - offset,
+                                    iov_iter_count(ii));
+
+               bytes = min_t(size_t, bytes, fc->max_write - count);
+
+ again:
+               err = -EFAULT;
+               if (iov_iter_fault_in_readable(ii, bytes))
+                       break;
+
+               err = -ENOMEM;
+               page = __grab_cache_page(mapping, index);
+               if (!page)
+                       break;
+
+               pagefault_disable();
+               tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes);
+               pagefault_enable();
+               flush_dcache_page(page);
+
+               if (!tmp) {
+                       unlock_page(page);
+                       page_cache_release(page);
+                       bytes = min(bytes, iov_iter_single_seg_count(ii));
+                       goto again;
+               }
+
+               err = 0;
+               req->pages[req->num_pages] = page;
+               req->num_pages++;
+
+               iov_iter_advance(ii, tmp);
+               count += tmp;
+               pos += tmp;
+               offset += tmp;
+               if (offset == PAGE_CACHE_SIZE)
+                       offset = 0;
+
+       } while (iov_iter_count(ii) && count < fc->max_write &&
+                req->num_pages < FUSE_MAX_PAGES_PER_REQ && offset == 0);
+
+       return count > 0 ? count : err;
+}
+
+static ssize_t fuse_perform_write(struct file *file,
+                                 struct address_space *mapping,
+                                 struct iov_iter *ii, loff_t pos)
+{
+       struct inode *inode = mapping->host;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       int err = 0;
+       ssize_t res = 0;
+
+       if (is_bad_inode(inode))
+               return -EIO;
+
+       do {
+               struct fuse_req *req;
+               ssize_t count;
+
+               req = fuse_get_req(fc);
+               if (IS_ERR(req)) {
+                       err = PTR_ERR(req);
+                       break;
+               }
+
+               count = fuse_fill_write_pages(req, mapping, ii, pos);
+               if (count <= 0) {
+                       err = count;
+               } else {
+                       size_t num_written;
+
+                       num_written = fuse_send_write_pages(req, file, inode,
+                                                           pos, count);
+                       err = req->out.h.error;
+                       if (!err) {
+                               res += num_written;
+                               pos += num_written;
+
+                               /* break out of the loop on short write */
+                               if (num_written != count)
+                                       err = -EIO;
+                       }
+               }
+               fuse_put_request(fc, req);
+       } while (!err && iov_iter_count(ii));
+
+       if (res > 0)
+               fuse_write_update_size(inode, pos);
+
+       fuse_invalidate_attr(inode);
+
+       return res > 0 ? res : err;
+}
+
+static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+                                  unsigned long nr_segs, loff_t pos)
+{
+       struct file *file = iocb->ki_filp;
+       struct address_space *mapping = file->f_mapping;
+       size_t count = 0;
+       ssize_t written = 0;
+       struct inode *inode = mapping->host;
+       ssize_t err;
+       struct iov_iter i;
+
+       WARN_ON(iocb->ki_pos != pos);
+
+       err = generic_segment_checks(iov, &nr_segs, &count, VERIFY_READ);
+       if (err)
+               return err;
+
+       mutex_lock(&inode->i_mutex);
+       vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
+
+       /* We can write back this queue in page reclaim */
+       current->backing_dev_info = mapping->backing_dev_info;
+
+       err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
+       if (err)
+               goto out;
+
+       if (count == 0)
+               goto out;
+
+       err = remove_suid(file->f_path.dentry);
+       if (err)
+               goto out;
+
+       file_update_time(file);
+
+       iov_iter_init(&i, iov, nr_segs, count, 0);
+       written = fuse_perform_write(file, mapping, &i, pos);
+       if (written >= 0)
+               iocb->ki_pos = pos + written;
+
+out:
+       current->backing_dev_info = NULL;
+       mutex_unlock(&inode->i_mutex);
+
+       return written ? written : err;
+}
+
 static void fuse_release_user_pages(struct fuse_req *req, int write)
 {
        unsigned i;
@@ -645,14 +966,15 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
 
        while (count) {
                size_t nres;
-               size_t nbytes = min(count, nmax);
-               int err = fuse_get_user_pages(req, buf, nbytes, !write);
+               size_t nbytes_limit = min(count, nmax);
+               size_t nbytes;
+               int err = fuse_get_user_pages(req, buf, nbytes_limit, !write);
                if (err) {
                        res = err;
                        break;
                }
                nbytes = (req->num_pages << PAGE_SHIFT) - req->page_offset;
-               nbytes = min(count, nbytes);
+               nbytes = min(nbytes_limit, nbytes);
                if (write)
                        nres = fuse_send_write(req, file, inode, pos, nbytes,
                                               current->files);
@@ -683,12 +1005,8 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
        }
        fuse_put_request(fc, req);
        if (res > 0) {
-               if (write) {
-                       spin_lock(&fc->lock);
-                       if (pos > inode->i_size)
-                               i_size_write(inode, pos);
-                       spin_unlock(&fc->lock);
-               }
+               if (write)
+                       fuse_write_update_size(inode, pos);
                *ppos = pos;
        }
        fuse_invalidate_attr(inode);
@@ -716,21 +1034,225 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
        return res;
 }
 
-static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
+static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req)
 {
-       if ((vma->vm_flags & VM_SHARED)) {
-               if ((vma->vm_flags & VM_WRITE))
-                       return -ENODEV;
-               else
-                       vma->vm_flags &= ~VM_MAYWRITE;
+       __free_page(req->pages[0]);
+       fuse_file_put(req->ff);
+       fuse_put_request(fc, req);
+}
+
+static void fuse_writepage_finish(struct fuse_conn *fc, struct fuse_req *req)
+{
+       struct inode *inode = req->inode;
+       struct fuse_inode *fi = get_fuse_inode(inode);
+       struct backing_dev_info *bdi = inode->i_mapping->backing_dev_info;
+
+       list_del(&req->writepages_entry);
+       dec_bdi_stat(bdi, BDI_WRITEBACK);
+       dec_zone_page_state(req->pages[0], NR_WRITEBACK_TEMP);
+       bdi_writeout_inc(bdi);
+       wake_up(&fi->page_waitq);
+}
+
+/* Called under fc->lock, may release and reacquire it */
+static void fuse_send_writepage(struct fuse_conn *fc, struct fuse_req *req)
+{
+       struct fuse_inode *fi = get_fuse_inode(req->inode);
+       loff_t size = i_size_read(req->inode);
+       struct fuse_write_in *inarg = &req->misc.write.in;
+
+       if (!fc->connected)
+               goto out_free;
+
+       if (inarg->offset + PAGE_CACHE_SIZE <= size) {
+               inarg->size = PAGE_CACHE_SIZE;
+       } else if (inarg->offset < size) {
+               inarg->size = size & (PAGE_CACHE_SIZE - 1);
+       } else {
+               /* Got truncated off completely */
+               goto out_free;
+       }
+
+       req->in.args[1].size = inarg->size;
+       fi->writectr++;
+       request_send_background_locked(fc, req);
+       return;
+
+ out_free:
+       fuse_writepage_finish(fc, req);
+       spin_unlock(&fc->lock);
+       fuse_writepage_free(fc, req);
+       spin_lock(&fc->lock);
+}
+
+/*
+ * If fi->writectr is positive (no truncate or fsync going on) send
+ * all queued writepage requests.
+ *
+ * Called with fc->lock
+ */
+void fuse_flush_writepages(struct inode *inode)
+{
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_inode *fi = get_fuse_inode(inode);
+       struct fuse_req *req;
+
+       while (fi->writectr >= 0 && !list_empty(&fi->queued_writes)) {
+               req = list_entry(fi->queued_writes.next, struct fuse_req, list);
+               list_del_init(&req->list);
+               fuse_send_writepage(fc, req);
+       }
+}
+
+static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_req *req)
+{
+       struct inode *inode = req->inode;
+       struct fuse_inode *fi = get_fuse_inode(inode);
+
+       mapping_set_error(inode->i_mapping, req->out.h.error);
+       spin_lock(&fc->lock);
+       fi->writectr--;
+       fuse_writepage_finish(fc, req);
+       spin_unlock(&fc->lock);
+       fuse_writepage_free(fc, req);
+}
+
+static int fuse_writepage_locked(struct page *page)
+{
+       struct address_space *mapping = page->mapping;
+       struct inode *inode = mapping->host;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_inode *fi = get_fuse_inode(inode);
+       struct fuse_req *req;
+       struct fuse_file *ff;
+       struct page *tmp_page;
+
+       set_page_writeback(page);
+
+       req = fuse_request_alloc_nofs();
+       if (!req)
+               goto err;
+
+       tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
+       if (!tmp_page)
+               goto err_free;
+
+       spin_lock(&fc->lock);
+       BUG_ON(list_empty(&fi->write_files));
+       ff = list_entry(fi->write_files.next, struct fuse_file, write_entry);
+       req->ff = fuse_file_get(ff);
+       spin_unlock(&fc->lock);
+
+       fuse_write_fill(req, NULL, ff, inode, page_offset(page), 0, 1);
+
+       copy_highpage(tmp_page, page);
+       req->num_pages = 1;
+       req->pages[0] = tmp_page;
+       req->page_offset = 0;
+       req->end = fuse_writepage_end;
+       req->inode = inode;
+
+       inc_bdi_stat(mapping->backing_dev_info, BDI_WRITEBACK);
+       inc_zone_page_state(tmp_page, NR_WRITEBACK_TEMP);
+       end_page_writeback(page);
+
+       spin_lock(&fc->lock);
+       list_add(&req->writepages_entry, &fi->writepages);
+       list_add_tail(&req->list, &fi->queued_writes);
+       fuse_flush_writepages(inode);
+       spin_unlock(&fc->lock);
+
+       return 0;
+
+err_free:
+       fuse_request_free(req);
+err:
+       end_page_writeback(page);
+       return -ENOMEM;
+}
+
+static int fuse_writepage(struct page *page, struct writeback_control *wbc)
+{
+       int err;
+
+       err = fuse_writepage_locked(page);
+       unlock_page(page);
+
+       return err;
+}
+
+static int fuse_launder_page(struct page *page)
+{
+       int err = 0;
+       if (clear_page_dirty_for_io(page)) {
+               struct inode *inode = page->mapping->host;
+               err = fuse_writepage_locked(page);
+               if (!err)
+                       fuse_wait_on_page_writeback(inode, page->index);
        }
-       return generic_file_mmap(file, vma);
+       return err;
 }
 
-static int fuse_set_page_dirty(struct page *page)
+/*
+ * Write back dirty pages now, because there may not be any suitable
+ * open files later
+ */
+static void fuse_vma_close(struct vm_area_struct *vma)
 {
-       printk("fuse_set_page_dirty: should not happen\n");
-       dump_stack();
+       filemap_write_and_wait(vma->vm_file->f_mapping);
+}
+
+/*
+ * Wait for writeback against this page to complete before allowing it
+ * to be marked dirty again, and hence written back again, possibly
+ * before the previous writepage completed.
+ *
+ * Block here, instead of in ->writepage(), so that the userspace fs
+ * can only block processes actually operating on the filesystem.
+ *
+ * Otherwise unprivileged userspace fs would be able to block
+ * unrelated:
+ *
+ * - page migration
+ * - sync(2)
+ * - try_to_free_pages() with order > PAGE_ALLOC_COSTLY_ORDER
+ */
+static int fuse_page_mkwrite(struct vm_area_struct *vma, struct page *page)
+{
+       /*
+        * Don't use page->mapping as it may become NULL from a
+        * concurrent truncate.
+        */
+       struct inode *inode = vma->vm_file->f_mapping->host;
+
+       fuse_wait_on_page_writeback(inode, page->index);
+       return 0;
+}
+
+static struct vm_operations_struct fuse_file_vm_ops = {
+       .close          = fuse_vma_close,
+       .fault          = filemap_fault,
+       .page_mkwrite   = fuse_page_mkwrite,
+};
+
+static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) {
+               struct inode *inode = file->f_dentry->d_inode;
+               struct fuse_conn *fc = get_fuse_conn(inode);
+               struct fuse_inode *fi = get_fuse_inode(inode);
+               struct fuse_file *ff = file->private_data;
+               /*
+                * file may be written through mmap, so chain it onto the
+                * inodes's write_file list
+                */
+               spin_lock(&fc->lock);
+               if (list_empty(&ff->write_entry))
+                       list_add(&ff->write_entry, &fi->write_files);
+               spin_unlock(&fc->lock);
+       }
+       file_accessed(file);
+       vma->vm_ops = &fuse_file_vm_ops;
        return 0;
 }
 
@@ -909,12 +1431,37 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
        return err ? 0 : outarg.block;
 }
 
+static loff_t fuse_file_llseek(struct file *file, loff_t offset, int origin)
+{
+       loff_t retval;
+       struct inode *inode = file->f_path.dentry->d_inode;
+
+       mutex_lock(&inode->i_mutex);
+       switch (origin) {
+       case SEEK_END:
+               offset += i_size_read(inode);
+               break;
+       case SEEK_CUR:
+               offset += file->f_pos;
+       }
+       retval = -EINVAL;
+       if (offset >= 0 && offset <= inode->i_sb->s_maxbytes) {
+               if (offset != file->f_pos) {
+                       file->f_pos = offset;
+                       file->f_version = 0;
+               }
+               retval = offset;
+       }
+       mutex_unlock(&inode->i_mutex);
+       return retval;
+}
+
 static const struct file_operations fuse_file_operations = {
-       .llseek         = generic_file_llseek,
+       .llseek         = fuse_file_llseek,
        .read           = do_sync_read,
        .aio_read       = fuse_file_aio_read,
        .write          = do_sync_write,
-       .aio_write      = generic_file_aio_write,
+       .aio_write      = fuse_file_aio_write,
        .mmap           = fuse_file_mmap,
        .open           = fuse_open,
        .flush          = fuse_flush,
@@ -926,7 +1473,7 @@ static const struct file_operations fuse_file_operations = {
 };
 
 static const struct file_operations fuse_direct_io_file_operations = {
-       .llseek         = generic_file_llseek,
+       .llseek         = fuse_file_llseek,
        .read           = fuse_direct_read,
        .write          = fuse_direct_write,
        .open           = fuse_open,
@@ -940,10 +1487,12 @@ static const struct file_operations fuse_direct_io_file_operations = {
 
 static const struct address_space_operations fuse_file_aops  = {
        .readpage       = fuse_readpage,
+       .writepage      = fuse_writepage,
+       .launder_page   = fuse_launder_page,
        .write_begin    = fuse_write_begin,
        .write_end      = fuse_write_end,
        .readpages      = fuse_readpages,
-       .set_page_dirty = fuse_set_page_dirty,
+       .set_page_dirty = __set_page_dirty_nobuffers,
        .bmap           = fuse_bmap,
 };
 
index 67aaf6ee38eaaeb1fedd9c313a160f623d58b8c3..dadffa21a206d220307e9b3e1212b09080bf5741 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/mm.h>
 #include <linux/backing-dev.h>
 #include <linux/mutex.h>
+#include <linux/rwsem.h>
 
 /** Max number of pages that can be used in a single read request */
 #define FUSE_MAX_PAGES_PER_REQ 32
@@ -25,6 +26,9 @@
 /** Congestion starts at 75% of maximum */
 #define FUSE_CONGESTION_THRESHOLD (FUSE_MAX_BACKGROUND * 75 / 100)
 
+/** Bias for fi->writectr, meaning new writepages must not be sent */
+#define FUSE_NOWRITE INT_MIN
+
 /** It could be as large as PATH_MAX, but would that have any uses? */
 #define FUSE_NAME_MAX 1024
 
@@ -73,6 +77,19 @@ struct fuse_inode {
 
        /** Files usable in writepage.  Protected by fc->lock */
        struct list_head write_files;
+
+       /** Writepages pending on truncate or fsync */
+       struct list_head queued_writes;
+
+       /** Number of sent writes, a negative bias (FUSE_NOWRITE)
+        * means more writes are blocked */
+       int writectr;
+
+       /** Waitq for writepage completion */
+       wait_queue_head_t page_waitq;
+
+       /** List of writepage requestst (pending or sent) */
+       struct list_head writepages;
 };
 
 /** FUSE specific file data */
@@ -222,7 +239,10 @@ struct fuse_req {
                } release;
                struct fuse_init_in init_in;
                struct fuse_init_out init_out;
-               struct fuse_read_in read_in;
+               struct {
+                       struct fuse_read_in in;
+                       u64 attr_ver;
+               } read;
                struct {
                        struct fuse_write_in in;
                        struct fuse_write_out out;
@@ -242,6 +262,12 @@ struct fuse_req {
        /** File used in the request (or NULL) */
        struct fuse_file *ff;
 
+       /** Inode used in the request or NULL */
+       struct inode *inode;
+
+       /** Link on fi->writepages */
+       struct list_head writepages_entry;
+
        /** Request completion callback */
        void (*end)(struct fuse_conn *, struct fuse_req *);
 
@@ -390,8 +416,8 @@ struct fuse_conn {
        /** Entry on the fuse_conn_list */
        struct list_head entry;
 
-       /** Unique ID */
-       u64 id;
+       /** Device ID from super block */
+       dev_t dev;
 
        /** Dentries in the control filesystem */
        struct dentry *ctl_dentry[FUSE_CTL_NUM_DENTRIES];
@@ -438,7 +464,7 @@ extern const struct file_operations fuse_dev_operations;
 /**
  * Get a filled in inode
  */
-struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
+struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
                        int generation, struct fuse_attr *attr,
                        u64 attr_valid, u64 attr_version);
 
@@ -446,7 +472,7 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
  * Send FORGET command
  */
 void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
-                     unsigned long nodeid, u64 nlookup);
+                     u64 nodeid, u64 nlookup);
 
 /**
  * Initialize READ or READDIR request
@@ -504,6 +530,11 @@ void fuse_init_symlink(struct inode *inode);
 void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
                            u64 attr_valid, u64 attr_version);
 
+void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
+                                  u64 attr_valid);
+
+void fuse_truncate(struct address_space *mapping, loff_t offset);
+
 /**
  * Initialize the client device
  */
@@ -522,6 +553,8 @@ void fuse_ctl_cleanup(void);
  */
 struct fuse_req *fuse_request_alloc(void);
 
+struct fuse_req *fuse_request_alloc_nofs(void);
+
 /**
  * Free a request
  */
@@ -558,6 +591,8 @@ void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req);
  */
 void request_send_background(struct fuse_conn *fc, struct fuse_req *req);
 
+void request_send_background_locked(struct fuse_conn *fc, struct fuse_req *req);
+
 /* Abort all requests */
 void fuse_abort_conn(struct fuse_conn *fc);
 
@@ -600,3 +635,10 @@ u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id);
 
 int fuse_update_attributes(struct inode *inode, struct kstat *stat,
                           struct file *file, bool *refreshed);
+
+void fuse_flush_writepages(struct inode *inode);
+
+void fuse_set_nowrite(struct inode *inode);
+void fuse_release_nowrite(struct inode *inode);
+
+u64 fuse_get_attr_version(struct fuse_conn *fc);
index 4df34da2284aaf1cf9b96ee995afb03fd408209a..79b61587383832f7a7ff2187642f0fdcc509f047 100644 (file)
@@ -59,7 +59,11 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
        fi->nodeid = 0;
        fi->nlookup = 0;
        fi->attr_version = 0;
+       fi->writectr = 0;
        INIT_LIST_HEAD(&fi->write_files);
+       INIT_LIST_HEAD(&fi->queued_writes);
+       INIT_LIST_HEAD(&fi->writepages);
+       init_waitqueue_head(&fi->page_waitq);
        fi->forget_req = fuse_request_alloc();
        if (!fi->forget_req) {
                kmem_cache_free(fuse_inode_cachep, inode);
@@ -73,13 +77,14 @@ static void fuse_destroy_inode(struct inode *inode)
 {
        struct fuse_inode *fi = get_fuse_inode(inode);
        BUG_ON(!list_empty(&fi->write_files));
+       BUG_ON(!list_empty(&fi->queued_writes));
        if (fi->forget_req)
                fuse_request_free(fi->forget_req);
        kmem_cache_free(fuse_inode_cachep, inode);
 }
 
 void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
-                     unsigned long nodeid, u64 nlookup)
+                     u64 nodeid, u64 nlookup)
 {
        struct fuse_forget_in *inarg = &req->misc.forget_in;
        inarg->nlookup = nlookup;
@@ -109,7 +114,7 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data)
        return 0;
 }
 
-static void fuse_truncate(struct address_space *mapping, loff_t offset)
+void fuse_truncate(struct address_space *mapping, loff_t offset)
 {
        /* See vmtruncate() */
        unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
@@ -117,19 +122,12 @@ static void fuse_truncate(struct address_space *mapping, loff_t offset)
        unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
 }
 
-
-void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
-                           u64 attr_valid, u64 attr_version)
+void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
+                                  u64 attr_valid)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_inode *fi = get_fuse_inode(inode);
-       loff_t oldsize;
 
-       spin_lock(&fc->lock);
-       if (attr_version != 0 && fi->attr_version > attr_version) {
-               spin_unlock(&fc->lock);
-               return;
-       }
        fi->attr_version = ++fc->attr_version;
        fi->i_time = attr_valid;
 
@@ -159,6 +157,22 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
        fi->orig_i_mode = inode->i_mode;
        if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
                inode->i_mode &= ~S_ISVTX;
+}
+
+void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
+                           u64 attr_valid, u64 attr_version)
+{
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_inode *fi = get_fuse_inode(inode);
+       loff_t oldsize;
+
+       spin_lock(&fc->lock);
+       if (attr_version != 0 && fi->attr_version > attr_version) {
+               spin_unlock(&fc->lock);
+               return;
+       }
+
+       fuse_change_attributes_common(inode, attr, attr_valid);
 
        oldsize = inode->i_size;
        i_size_write(inode, attr->size);
@@ -193,7 +207,7 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
 
 static int fuse_inode_eq(struct inode *inode, void *_nodeidp)
 {
-       unsigned long nodeid = *(unsigned long *) _nodeidp;
+       u64 nodeid = *(u64 *) _nodeidp;
        if (get_node_id(inode) == nodeid)
                return 1;
        else
@@ -202,12 +216,12 @@ static int fuse_inode_eq(struct inode *inode, void *_nodeidp)
 
 static int fuse_inode_set(struct inode *inode, void *_nodeidp)
 {
-       unsigned long nodeid = *(unsigned long *) _nodeidp;
+       u64 nodeid = *(u64 *) _nodeidp;
        get_fuse_inode(inode)->nodeid = nodeid;
        return 0;
 }
 
-struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
+struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
                        int generation, struct fuse_attr *attr,
                        u64 attr_valid, u64 attr_version)
 {
@@ -447,7 +461,7 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt)
        return 0;
 }
 
-static struct fuse_conn *new_conn(void)
+static struct fuse_conn *new_conn(struct super_block *sb)
 {
        struct fuse_conn *fc;
        int err;
@@ -468,19 +482,41 @@ static struct fuse_conn *new_conn(void)
                atomic_set(&fc->num_waiting, 0);
                fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
                fc->bdi.unplug_io_fn = default_unplug_io_fn;
+               /* fuse does it's own writeback accounting */
+               fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB;
+               fc->dev = sb->s_dev;
                err = bdi_init(&fc->bdi);
-               if (err) {
-                       kfree(fc);
-                       fc = NULL;
-                       goto out;
-               }
+               if (err)
+                       goto error_kfree;
+               err = bdi_register_dev(&fc->bdi, fc->dev);
+               if (err)
+                       goto error_bdi_destroy;
+               /*
+                * For a single fuse filesystem use max 1% of dirty +
+                * writeback threshold.
+                *
+                * This gives about 1M of write buffer for memory maps on a
+                * machine with 1G and 10% dirty_ratio, which should be more
+                * than enough.
+                *
+                * Privileged users can raise it by writing to
+                *
+                *    /sys/class/bdi/<bdi>/max_ratio
+                */
+               bdi_set_max_ratio(&fc->bdi, 1);
                fc->reqctr = 0;
                fc->blocked = 1;
                fc->attr_version = 1;
                get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key));
        }
-out:
        return fc;
+
+error_bdi_destroy:
+       bdi_destroy(&fc->bdi);
+error_kfree:
+       mutex_destroy(&fc->inst_mutex);
+       kfree(fc);
+       return NULL;
 }
 
 void fuse_conn_put(struct fuse_conn *fc)
@@ -548,6 +584,7 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
                fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages);
                fc->minor = arg->minor;
                fc->max_write = arg->minor < 5 ? 4096 : arg->max_write;
+               fc->max_write = min_t(unsigned, 4096, fc->max_write);
                fc->conn_init = 1;
        }
        fuse_put_request(fc, req);
@@ -578,12 +615,6 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
        request_send_background(fc, req);
 }
 
-static u64 conn_id(void)
-{
-       static u64 ctr = 1;
-       return ctr++;
-}
-
 static int fuse_fill_super(struct super_block *sb, void *data, int silent)
 {
        struct fuse_conn *fc;
@@ -621,14 +652,14 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
        if (file->f_op != &fuse_dev_operations)
                return -EINVAL;
 
-       fc = new_conn();
+       fc = new_conn(sb);
        if (!fc)
                return -ENOMEM;
 
        fc->flags = d.flags;
        fc->user_id = d.user_id;
        fc->group_id = d.group_id;
-       fc->max_read = d.max_read;
+       fc->max_read = min_t(unsigned, 4096, d.max_read);
 
        /* Used by get_root_inode() */
        sb->s_fs_info = fc;
@@ -659,7 +690,6 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
        if (file->private_data)
                goto err_unlock;
 
-       fc->id = conn_id();
        err = fuse_ctl_add_conn(fc);
        if (err)
                goto err_unlock;
index 8479da47049cbe163c8d642c1cbc8fe30532ee39..a4ff271df9ee4432eb52ceb16f59cb65a0af1f87 100644 (file)
@@ -212,7 +212,7 @@ int gdlm_sysfs_init(void)
 {
        gdlm_kset = kset_create_and_add("lock_dlm", NULL, kernel_kobj);
        if (!gdlm_kset) {
-               printk(KERN_WARNING "%s: can not create kset\n", __FUNCTION__);
+               printk(KERN_WARNING "%s: can not create kset\n", __func__);
                return -ENOMEM;
        }
        return 0;
index 509c5d60bd803ecc928df4aad578eb8856ae9ffa..7f48576289c9f9a916aee237d6b2d6308f2bb93b 100644 (file)
@@ -41,7 +41,7 @@ int gfs2_assert_withdraw_i(struct gfs2_sbd *sdp, char *assertion,
 
 #define gfs2_assert_withdraw(sdp, assertion) \
 ((likely(assertion)) ? 0 : gfs2_assert_withdraw_i((sdp), #assertion, \
-                                       __FUNCTION__, __FILE__, __LINE__))
+                                       __func__, __FILE__, __LINE__))
 
 
 int gfs2_assert_warn_i(struct gfs2_sbd *sdp, char *assertion,
@@ -49,28 +49,28 @@ int gfs2_assert_warn_i(struct gfs2_sbd *sdp, char *assertion,
 
 #define gfs2_assert_warn(sdp, assertion) \
 ((likely(assertion)) ? 0 : gfs2_assert_warn_i((sdp), #assertion, \
-                                       __FUNCTION__, __FILE__, __LINE__))
+                                       __func__, __FILE__, __LINE__))
 
 
 int gfs2_consist_i(struct gfs2_sbd *sdp, int cluster_wide,
                   const char *function, char *file, unsigned int line);
 
 #define gfs2_consist(sdp) \
-gfs2_consist_i((sdp), 0, __FUNCTION__, __FILE__, __LINE__)
+gfs2_consist_i((sdp), 0, __func__, __FILE__, __LINE__)
 
 
 int gfs2_consist_inode_i(struct gfs2_inode *ip, int cluster_wide,
                         const char *function, char *file, unsigned int line);
 
 #define gfs2_consist_inode(ip) \
-gfs2_consist_inode_i((ip), 0, __FUNCTION__, __FILE__, __LINE__)
+gfs2_consist_inode_i((ip), 0, __func__, __FILE__, __LINE__)
 
 
 int gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd, int cluster_wide,
                         const char *function, char *file, unsigned int line);
 
 #define gfs2_consist_rgrpd(rgd) \
-gfs2_consist_rgrpd_i((rgd), 0, __FUNCTION__, __FILE__, __LINE__)
+gfs2_consist_rgrpd_i((rgd), 0, __func__, __FILE__, __LINE__)
 
 
 int gfs2_meta_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
@@ -91,7 +91,7 @@ static inline int gfs2_meta_check_i(struct gfs2_sbd *sdp,
 }
 
 #define gfs2_meta_check(sdp, bh) \
-gfs2_meta_check_i((sdp), (bh), __FUNCTION__, __FILE__, __LINE__)
+gfs2_meta_check_i((sdp), (bh), __func__, __FILE__, __LINE__)
 
 
 int gfs2_metatype_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
@@ -118,7 +118,7 @@ static inline int gfs2_metatype_check_i(struct gfs2_sbd *sdp,
 }
 
 #define gfs2_metatype_check(sdp, bh, type) \
-gfs2_metatype_check_i((sdp), (bh), (type), __FUNCTION__, __FILE__, __LINE__)
+gfs2_metatype_check_i((sdp), (bh), (type), __func__, __FILE__, __LINE__)
 
 static inline void gfs2_metatype_set(struct buffer_head *bh, u16 type,
                                     u16 format)
@@ -134,14 +134,14 @@ int gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function,
                    char *file, unsigned int line);
 
 #define gfs2_io_error(sdp) \
-gfs2_io_error_i((sdp), __FUNCTION__, __FILE__, __LINE__);
+gfs2_io_error_i((sdp), __func__, __FILE__, __LINE__);
 
 
 int gfs2_io_error_bh_i(struct gfs2_sbd *sdp, struct buffer_head *bh,
                       const char *function, char *file, unsigned int line);
 
 #define gfs2_io_error_bh(sdp, bh) \
-gfs2_io_error_bh_i((sdp), (bh), __FUNCTION__, __FILE__, __LINE__);
+gfs2_io_error_bh_i((sdp), (bh), __func__, __FILE__, __LINE__);
 
 
 extern struct kmem_cache *gfs2_glock_cachep;
index 24cf6fc4302122366ed444c7f5f3344b7cae7382..f6621a785202b9f3d26f562bd7402cfbedb589a9 100644 (file)
@@ -208,7 +208,9 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
        struct hfs_bnode *node, *next_node;
        struct page **pagep;
        u32 nidx, idx;
-       u16 off, len;
+       unsigned off;
+       u16 off16;
+       u16 len;
        u8 *data, byte, m;
        int i;
 
@@ -235,7 +237,8 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
        node = hfs_bnode_find(tree, nidx);
        if (IS_ERR(node))
                return node;
-       len = hfs_brec_lenoff(node, 2, &off);
+       len = hfs_brec_lenoff(node, 2, &off16);
+       off = off16;
 
        off += node->page_offset;
        pagep = node->page + (off >> PAGE_CACHE_SHIFT);
@@ -280,7 +283,8 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
                        return next_node;
                node = next_node;
 
-               len = hfs_brec_lenoff(node, 0, &off);
+               len = hfs_brec_lenoff(node, 0, &off16);
+               off = off16;
                off += node->page_offset;
                pagep = node->page + (off >> PAGE_CACHE_SHIFT);
                data = kmap(*pagep);
index b4651e128d7fbb8e25a3b1767ef1f967ea08b6f0..36ca2e1a4fa32b82f937fa415f77a92addfdd022 100644 (file)
@@ -215,7 +215,7 @@ int hfs_mdb_get(struct super_block *sb)
                attrib &= cpu_to_be16(~HFS_SB_ATTRIB_UNMNT);
                attrib |= cpu_to_be16(HFS_SB_ATTRIB_INCNSTNT);
                mdb->drAtrb = attrib;
-               mdb->drWrCnt = cpu_to_be32(be32_to_cpu(mdb->drWrCnt) + 1);
+               be32_add_cpu(&mdb->drWrCnt, 1);
                mdb->drLsMod = hfs_mtime();
 
                mark_buffer_dirty(HFS_SB(sb)->mdb_bh);
index 32de44ed002196c5b3fd327662dc123f9899f8ac..8cf67974adf60ad79f1b88da04ba4d4fb71f3b68 100644 (file)
@@ -297,7 +297,8 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
                                return 0;
                        }
                        p = match_strdup(&args[0]);
-                       hsb->nls_disk = load_nls(p);
+                       if (p)
+                               hsb->nls_disk = load_nls(p);
                        if (!hsb->nls_disk) {
                                printk(KERN_ERR "hfs: unable to load codepage \"%s\"\n", p);
                                kfree(p);
@@ -311,7 +312,8 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
                                return 0;
                        }
                        p = match_strdup(&args[0]);
-                       hsb->nls_io = load_nls(p);
+                       if (p)
+                               hsb->nls_io = load_nls(p);
                        if (!hsb->nls_io) {
                                printk(KERN_ERR "hfs: unable to load iocharset \"%s\"\n", p);
                                kfree(p);
index bb5433608a42efdf3c6ec0ef9b809c614a11b686..e49fcee1e293f725786e84ea6126e408e5eda7c8 100644 (file)
@@ -184,7 +184,9 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
        struct hfs_bnode *node, *next_node;
        struct page **pagep;
        u32 nidx, idx;
-       u16 off, len;
+       unsigned off;
+       u16 off16;
+       u16 len;
        u8 *data, byte, m;
        int i;
 
@@ -211,7 +213,8 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
        node = hfs_bnode_find(tree, nidx);
        if (IS_ERR(node))
                return node;
-       len = hfs_brec_lenoff(node, 2, &off);
+       len = hfs_brec_lenoff(node, 2, &off16);
+       off = off16;
 
        off += node->page_offset;
        pagep = node->page + (off >> PAGE_CACHE_SHIFT);
@@ -256,7 +259,8 @@ struct hfs_bnode *hfs_bmap_alloc(struct hfs_btree *tree)
                        return next_node;
                node = next_node;
 
-               len = hfs_brec_lenoff(node, 0, &off);
+               len = hfs_brec_lenoff(node, 0, &off16);
+               off = off16;
                off += node->page_offset;
                pagep = node->page + (off >> PAGE_CACHE_SHIFT);
                data = kmap(*pagep);
index d72d0a8b25aacf39fd819da29c0963a441f9718a..9e59537b43d56ef0ca178acce4ec900b7d50fcff 100644 (file)
@@ -311,6 +311,10 @@ int hfsplus_delete_cat(u32, struct inode *, struct qstr *);
 int hfsplus_rename_cat(u32, struct inode *, struct qstr *,
                       struct inode *, struct qstr *);
 
+/* dir.c */
+extern const struct inode_operations hfsplus_dir_inode_operations;
+extern const struct file_operations hfsplus_dir_operations;
+
 /* extents.c */
 int hfsplus_ext_cmp_key(const hfsplus_btree_key *, const hfsplus_btree_key *);
 void hfsplus_ext_write_extent(struct inode *);
index 37744cf3706ac4e7487c687974bda361eb0e873a..d53b2af91c25d78e39c17a692733224753e1905f 100644 (file)
@@ -278,9 +278,6 @@ static int hfsplus_file_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-extern const struct inode_operations hfsplus_dir_inode_operations;
-extern struct file_operations hfsplus_dir_operations;
-
 static const struct inode_operations hfsplus_file_inode_operations = {
        .lookup         = hfsplus_file_lookup,
        .truncate       = hfsplus_file_truncate,
index dc64fac008315092a6d878e5df8634735ea3bbb8..9997cbf8beb50ece6abfa28dc18f3223037eab01 100644 (file)
@@ -132,7 +132,8 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi)
                                return 0;
                        }
                        p = match_strdup(&args[0]);
-                       sbi->nls = load_nls(p);
+                       if (p)
+                               sbi->nls = load_nls(p);
                        if (!sbi->nls) {
                                printk(KERN_ERR "hfs: unable to load nls mapping \"%s\"\n", p);
                                kfree(p);
index b0f9ad362d1d45127a2391eb034e1c7e642448df..ce97a54518d81d8b904c7a01c336133516547eb3 100644 (file)
@@ -357,7 +357,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
                printk(KERN_WARNING "hfs: Filesystem is marked locked, mounting read-only.\n");
                sb->s_flags |= MS_RDONLY;
        } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) {
-               printk(KERN_WARNING "hfs: write access to a jounaled filesystem is not supported, "
+               printk(KERN_WARNING "hfs: write access to a journaled filesystem is not supported, "
                       "use the force option at your own risk, mounting read-only.\n");
                sb->s_flags |= MS_RDONLY;
        }
@@ -423,7 +423,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
         */
        vhdr->last_mount_vers = cpu_to_be32(HFSP_MOUNT_VERSION);
        vhdr->modify_date = hfsp_now2mt();
-       vhdr->write_count = cpu_to_be32(be32_to_cpu(vhdr->write_count) + 1);
+       be32_add_cpu(&vhdr->write_count, 1);
        vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT);
        vhdr->attributes |= cpu_to_be32(HFSPLUS_VOL_INCNSTNT);
        mark_buffer_dirty(HFSPLUS_SB(sb).s_vhbh);
index 72cab78f05091282843baef84d6e03abdc8263aa..175d08eacc868226d581d46a2101169bd103f096 100644 (file)
@@ -47,7 +47,7 @@ static int hfsplus_read_mdb(void *bufptr, struct hfsplus_wd *wd)
                return 0;
        wd->ablk_start = be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_ABLKSTART));
 
-       extent = be32_to_cpu(get_unaligned((__be32 *)(bufptr + HFSP_WRAPOFF_EMBEDEXT)));
+       extent = get_unaligned_be32(bufptr + HFSP_WRAPOFF_EMBEDEXT);
        wd->embed_start = (extent >> 16) & 0xFFFF;
        wd->embed_count = extent & 0xFFFF;
 
index 9783723e8ffe19d2e440930ea851c6aae5a6c097..aeabf80f81a5d38561768ea95d1b544605e5dcc4 100644 (file)
@@ -45,7 +45,7 @@ static const struct inode_operations hugetlbfs_inode_operations;
 
 static struct backing_dev_info hugetlbfs_backing_dev_info = {
        .ra_pages       = 0,    /* No readahead */
-       .capabilities   = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
+       .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK,
 };
 
 int sysctl_hugetlb_shm_group;
index 27ee1af50d02c6537febbaed5cf7bd60debc832d..bf64781304243f62cc1ff52f9f395724651103d7 100644 (file)
@@ -495,8 +495,7 @@ static struct inode * find_inode(struct super_block * sb, struct hlist_head *hea
        struct inode * inode = NULL;
 
 repeat:
-       hlist_for_each (node, head) { 
-               inode = hlist_entry(node, struct inode, i_hash);
+       hlist_for_each_entry(inode, node, head, i_hash) {
                if (inode->i_sb != sb)
                        continue;
                if (!test(inode, data))
@@ -520,8 +519,7 @@ static struct inode * find_inode_fast(struct super_block * sb, struct hlist_head
        struct inode * inode = NULL;
 
 repeat:
-       hlist_for_each (node, head) {
-               inode = hlist_entry(node, struct inode, i_hash);
+       hlist_for_each_entry(inode, node, head, i_hash) {
                if (inode->i_ino != ino)
                        continue;
                if (inode->i_sb != sb)
index 7b94a1e3c015468b30e6343156053fd5e409afca..6676c06bb7c16935b3a7fbc4615836f1dfb256fb 100644 (file)
@@ -598,7 +598,7 @@ asmlinkage long sys_inotify_init(void)
        }
 
        ih = inotify_init(&inotify_user_ops);
-       if (unlikely(IS_ERR(ih))) {
+       if (IS_ERR(ih)) {
                ret = PTR_ERR(ih);
                goto out_free_dev;
        }
index f32fbde2175e84d6bb3bc59fdeacc9860f5837b3..7db32b3382d3a66452388ad9e9023216a1855ab3 100644 (file)
@@ -28,8 +28,8 @@
  *
  * Returns 0 on success, -errno on error.
  */
-long vfs_ioctl(struct file *filp, unsigned int cmd,
-              unsigned long arg)
+static long vfs_ioctl(struct file *filp, unsigned int cmd,
+                     unsigned long arg)
 {
        int error = -ENOTTY;
 
index 1ba407c64df1fed39edbe1470538dd49da171a61..2f0dc5a1463306adcecc3296a8cf6b01defb7fe3 100644 (file)
@@ -145,6 +145,14 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
                        }
                        de = tmpde;
                }
+               /* Basic sanity check, whether name doesn't exceed dir entry */
+               if (de_len < de->name_len[0] +
+                                       sizeof(struct iso_directory_record)) {
+                       printk(KERN_NOTICE "iso9660: Corrupted directory entry"
+                              " in block %lu of inode %lu\n", block,
+                              inode->i_ino);
+                       return -EIO;
+               }
 
                if (first_de) {
                        isofs_normalize_block_and_offset(de,
index d1bdf8adb3510a98ffe2c49518ba6bdd272eaa2d..ccbf72faf27ada523b4abf8d1fa2dc1f42283e1e 100644 (file)
@@ -78,29 +78,29 @@ static inline int isonum_712(char *p)
 }
 static inline unsigned int isonum_721(char *p)
 {
-       return le16_to_cpu(get_unaligned((__le16 *)p));
+       return get_unaligned_le16(p);
 }
 static inline unsigned int isonum_722(char *p)
 {
-       return be16_to_cpu(get_unaligned((__le16 *)p));
+       return get_unaligned_be16(p);
 }
 static inline unsigned int isonum_723(char *p)
 {
        /* Ignore bigendian datum due to broken mastering programs */
-       return le16_to_cpu(get_unaligned((__le16 *)p));
+       return get_unaligned_le16(p);
 }
 static inline unsigned int isonum_731(char *p)
 {
-       return le32_to_cpu(get_unaligned((__le32 *)p));
+       return get_unaligned_le32(p);
 }
 static inline unsigned int isonum_732(char *p)
 {
-       return be32_to_cpu(get_unaligned((__le32 *)p));
+       return get_unaligned_be32(p);
 }
 static inline unsigned int isonum_733(char *p)
 {
        /* Ignore bigendian datum due to broken mastering programs */
-       return le32_to_cpu(get_unaligned((__le32 *)p));
+       return get_unaligned_le32(p);
 }
 extern int iso_date(char *, int);
 
index 344b247bc29ab1f104fcc25af9a831052267baad..8299889a835ea5c9b95c7d71afcabdb4610310c1 100644 (file)
@@ -111,6 +111,13 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
 
                dlen = de->name_len[0];
                dpnt = de->name;
+               /* Basic sanity check, whether name doesn't exceed dir entry */
+               if (de_len < dlen + sizeof(struct iso_directory_record)) {
+                       printk(KERN_NOTICE "iso9660: Corrupted directory entry"
+                              " in block %lu of inode %lu\n", block,
+                              dir->i_ino);
+                       return 0;
+               }
 
                if (sbi->s_rock &&
                    ((i = get_rock_ridge_filename(de, tmpname, dir)))) {
index a8173081f83124d316181460f06645514490355a..e0139786f717839ff5c7b5f542449593c1fcab54 100644 (file)
@@ -519,22 +519,6 @@ void jbd2_journal_commit_transaction(journal_t *journal)
 
        jbd_debug (3, "JBD: commit phase 2\n");
 
-       /*
-        * First, drop modified flag: all accesses to the buffers
-        * will be tracked for a new trasaction only -bzzz
-        */
-       spin_lock(&journal->j_list_lock);
-       if (commit_transaction->t_buffers) {
-               new_jh = jh = commit_transaction->t_buffers->b_tnext;
-               do {
-                       J_ASSERT_JH(new_jh, new_jh->b_modified == 1 ||
-                                       new_jh->b_modified == 0);
-                       new_jh->b_modified = 0;
-                       new_jh = new_jh->b_tnext;
-               } while (new_jh != jh);
-       }
-       spin_unlock(&journal->j_list_lock);
-
        /*
         * Now start flushing things to disk, in the order they appear
         * on the transaction lists.  Data blocks go first.
@@ -584,6 +568,9 @@ void jbd2_journal_commit_transaction(journal_t *journal)
        stats.u.run.rs_blocks = commit_transaction->t_outstanding_credits;
        stats.u.run.rs_blocks_logged = 0;
 
+       J_ASSERT(commit_transaction->t_nr_buffers <=
+                commit_transaction->t_outstanding_credits);
+
        descriptor = NULL;
        bufs = 0;
        while (commit_transaction->t_buffers) {
index 954cff001df6d1a9bf51a964774bc3d3eef13b79..53632e3e8457e6227a182b28ea0d75a49880c5f6 100644 (file)
@@ -534,7 +534,7 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid)
        if (!tid_geq(journal->j_commit_request, tid)) {
                printk(KERN_EMERG
                       "%s: error: j_commit_request=%d, tid=%d\n",
-                      __FUNCTION__, journal->j_commit_request, tid);
+                      __func__, journal->j_commit_request, tid);
        }
        spin_unlock(&journal->j_state_lock);
 #endif
@@ -599,7 +599,7 @@ int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr,
 
                        printk(KERN_ALERT "%s: journal block not found "
                                        "at offset %lu on %s\n",
-                               __FUNCTION__,
+                               __func__,
                                blocknr,
                                bdevname(journal->j_dev, b));
                        err = -EIO;
@@ -904,19 +904,10 @@ static void jbd2_stats_proc_init(journal_t *journal)
        snprintf(name, sizeof(name) - 1, "%s", bdevname(journal->j_dev, name));
        journal->j_proc_entry = proc_mkdir(name, proc_jbd2_stats);
        if (journal->j_proc_entry) {
-               struct proc_dir_entry *p;
-               p = create_proc_entry("history", S_IRUGO,
-                               journal->j_proc_entry);
-               if (p) {
-                       p->proc_fops = &jbd2_seq_history_fops;
-                       p->data = journal;
-                       p = create_proc_entry("info", S_IRUGO,
-                                               journal->j_proc_entry);
-                       if (p) {
-                               p->proc_fops = &jbd2_seq_info_fops;
-                               p->data = journal;
-                       }
-               }
+               proc_create_data("history", S_IRUGO, journal->j_proc_entry,
+                                &jbd2_seq_history_fops, journal);
+               proc_create_data("info", S_IRUGO, journal->j_proc_entry,
+                                &jbd2_seq_info_fops, journal);
        }
 }
 
@@ -1006,13 +997,14 @@ fail:
  */
 
 /**
- *  journal_t * jbd2_journal_init_dev() - creates an initialises a journal structure
+ *  journal_t * jbd2_journal_init_dev() - creates and initialises a journal structure
  *  @bdev: Block device on which to create the journal
  *  @fs_dev: Device which hold journalled filesystem for this journal.
  *  @start: Block nr Start of journal.
  *  @len:  Length of the journal in blocks.
  *  @blocksize: blocksize of journalling device
- *  @returns: a newly created journal_t *
+ *
+ *  Returns: a newly created journal_t *
  *
  *  jbd2_journal_init_dev creates a journal which maps a fixed contiguous
  *  range of blocks on an arbitrary block device.
@@ -1036,7 +1028,7 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev,
        journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
        if (!journal->j_wbuf) {
                printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
-                       __FUNCTION__);
+                       __func__);
                kfree(journal);
                journal = NULL;
                goto out;
@@ -1092,7 +1084,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode)
        journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
        if (!journal->j_wbuf) {
                printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
-                       __FUNCTION__);
+                       __func__);
                kfree(journal);
                return NULL;
        }
@@ -1101,7 +1093,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode)
        /* If that failed, give up */
        if (err) {
                printk(KERN_ERR "%s: Cannnot locate journal superblock\n",
-                      __FUNCTION__);
+                      __func__);
                kfree(journal);
                return NULL;
        }
@@ -1187,7 +1179,7 @@ int jbd2_journal_create(journal_t *journal)
                 */
                printk(KERN_EMERG
                       "%s: creation of journal on external device!\n",
-                      __FUNCTION__);
+                      __func__);
                BUG();
        }
 
@@ -1985,9 +1977,10 @@ static int journal_init_jbd2_journal_head_cache(void)
 
 static void jbd2_journal_destroy_jbd2_journal_head_cache(void)
 {
-       J_ASSERT(jbd2_journal_head_cache != NULL);
-       kmem_cache_destroy(jbd2_journal_head_cache);
-       jbd2_journal_head_cache = NULL;
+       if (jbd2_journal_head_cache) {
+               kmem_cache_destroy(jbd2_journal_head_cache);
+               jbd2_journal_head_cache = NULL;
+       }
 }
 
 /*
@@ -2006,7 +1999,7 @@ static struct journal_head *journal_alloc_journal_head(void)
                jbd_debug(1, "out of memory for journal_head\n");
                if (time_after(jiffies, last_warning + 5*HZ)) {
                        printk(KERN_NOTICE "ENOMEM in %s, retrying.\n",
-                              __FUNCTION__);
+                              __func__);
                        last_warning = jiffies;
                }
                while (!ret) {
@@ -2143,13 +2136,13 @@ static void __journal_remove_journal_head(struct buffer_head *bh)
                        if (jh->b_frozen_data) {
                                printk(KERN_WARNING "%s: freeing "
                                                "b_frozen_data\n",
-                                               __FUNCTION__);
+                                               __func__);
                                jbd2_free(jh->b_frozen_data, bh->b_size);
                        }
                        if (jh->b_committed_data) {
                                printk(KERN_WARNING "%s: freeing "
                                                "b_committed_data\n",
-                                               __FUNCTION__);
+                                               __func__);
                                jbd2_free(jh->b_committed_data, bh->b_size);
                        }
                        bh->b_private = NULL;
@@ -2314,10 +2307,12 @@ static int __init journal_init(void)
        BUILD_BUG_ON(sizeof(struct journal_superblock_s) != 1024);
 
        ret = journal_init_caches();
-       if (ret != 0)
+       if (ret == 0) {
+               jbd2_create_debugfs_entry();
+               jbd2_create_jbd_stats_proc_entry();
+       } else {
                jbd2_journal_destroy_caches();
-       jbd2_create_debugfs_entry();
-       jbd2_create_jbd_stats_proc_entry();
+       }
        return ret;
 }
 
index 2e1453a5e998d6a8dc606015a0b2ee953d365386..257ff26257655f4573669a5ab6cb7ee817e0371b 100644 (file)
@@ -139,7 +139,7 @@ repeat:
 oom:
        if (!journal_oom_retry)
                return -ENOMEM;
-       jbd_debug(1, "ENOMEM in %s, retrying\n", __FUNCTION__);
+       jbd_debug(1, "ENOMEM in %s, retrying\n", __func__);
        yield();
        goto repeat;
 }
@@ -167,138 +167,121 @@ static struct jbd2_revoke_record_s *find_revoke_record(journal_t *journal,
        return NULL;
 }
 
+void jbd2_journal_destroy_revoke_caches(void)
+{
+       if (jbd2_revoke_record_cache) {
+               kmem_cache_destroy(jbd2_revoke_record_cache);
+               jbd2_revoke_record_cache = NULL;
+       }
+       if (jbd2_revoke_table_cache) {
+               kmem_cache_destroy(jbd2_revoke_table_cache);
+               jbd2_revoke_table_cache = NULL;
+       }
+}
+
 int __init jbd2_journal_init_revoke_caches(void)
 {
+       J_ASSERT(!jbd2_revoke_record_cache);
+       J_ASSERT(!jbd2_revoke_table_cache);
+
        jbd2_revoke_record_cache = kmem_cache_create("jbd2_revoke_record",
                                           sizeof(struct jbd2_revoke_record_s),
                                           0,
                                           SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY,
                                           NULL);
        if (!jbd2_revoke_record_cache)
-               return -ENOMEM;
+               goto record_cache_failure;
 
        jbd2_revoke_table_cache = kmem_cache_create("jbd2_revoke_table",
                                           sizeof(struct jbd2_revoke_table_s),
                                           0, SLAB_TEMPORARY, NULL);
-       if (!jbd2_revoke_table_cache) {
-               kmem_cache_destroy(jbd2_revoke_record_cache);
-               jbd2_revoke_record_cache = NULL;
-               return -ENOMEM;
-       }
+       if (!jbd2_revoke_table_cache)
+               goto table_cache_failure;
        return 0;
+table_cache_failure:
+       jbd2_journal_destroy_revoke_caches();
+record_cache_failure:
+               return -ENOMEM;
 }
 
-void jbd2_journal_destroy_revoke_caches(void)
+static struct jbd2_revoke_table_s *jbd2_journal_init_revoke_table(int hash_size)
 {
-       kmem_cache_destroy(jbd2_revoke_record_cache);
-       jbd2_revoke_record_cache = NULL;
-       kmem_cache_destroy(jbd2_revoke_table_cache);
-       jbd2_revoke_table_cache = NULL;
-}
-
-/* Initialise the revoke table for a given journal to a given size. */
-
-int jbd2_journal_init_revoke(journal_t *journal, int hash_size)
-{
-       int shift, tmp;
+       int shift = 0;
+       int tmp = hash_size;
+       struct jbd2_revoke_table_s *table;
 
-       J_ASSERT (journal->j_revoke_table[0] == NULL);
+       table = kmem_cache_alloc(jbd2_revoke_table_cache, GFP_KERNEL);
+       if (!table)
+               goto out;
 
-       shift = 0;
-       tmp = hash_size;
        while((tmp >>= 1UL) != 0UL)
                shift++;
 
-       journal->j_revoke_table[0] = kmem_cache_alloc(jbd2_revoke_table_cache, GFP_KERNEL);
-       if (!journal->j_revoke_table[0])
-               return -ENOMEM;
-       journal->j_revoke = journal->j_revoke_table[0];
-
-       /* Check that the hash_size is a power of two */
-       J_ASSERT(is_power_of_2(hash_size));
-
-       journal->j_revoke->hash_size = hash_size;
-
-       journal->j_revoke->hash_shift = shift;
-
-       journal->j_revoke->hash_table =
+       table->hash_size = hash_size;
+       table->hash_shift = shift;
+       table->hash_table =
                kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL);
-       if (!journal->j_revoke->hash_table) {
-               kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[0]);
-               journal->j_revoke = NULL;
-               return -ENOMEM;
+       if (!table->hash_table) {
+               kmem_cache_free(jbd2_revoke_table_cache, table);
+               table = NULL;
+               goto out;
        }
 
        for (tmp = 0; tmp < hash_size; tmp++)
-               INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
+               INIT_LIST_HEAD(&table->hash_table[tmp]);
 
-       journal->j_revoke_table[1] = kmem_cache_alloc(jbd2_revoke_table_cache, GFP_KERNEL);
-       if (!journal->j_revoke_table[1]) {
-               kfree(journal->j_revoke_table[0]->hash_table);
-               kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[0]);
-               return -ENOMEM;
+out:
+       return table;
+}
+
+static void jbd2_journal_destroy_revoke_table(struct jbd2_revoke_table_s *table)
+{
+       int i;
+       struct list_head *hash_list;
+
+       for (i = 0; i < table->hash_size; i++) {
+               hash_list = &table->hash_table[i];
+               J_ASSERT(list_empty(hash_list));
        }
 
-       journal->j_revoke = journal->j_revoke_table[1];
+       kfree(table->hash_table);
+       kmem_cache_free(jbd2_revoke_table_cache, table);
+}
 
-       /* Check that the hash_size is a power of two */
+/* Initialise the revoke table for a given journal to a given size. */
+int jbd2_journal_init_revoke(journal_t *journal, int hash_size)
+{
+       J_ASSERT(journal->j_revoke_table[0] == NULL);
        J_ASSERT(is_power_of_2(hash_size));
 
-       journal->j_revoke->hash_size = hash_size;
-
-       journal->j_revoke->hash_shift = shift;
+       journal->j_revoke_table[0] = jbd2_journal_init_revoke_table(hash_size);
+       if (!journal->j_revoke_table[0])
+               goto fail0;
 
-       journal->j_revoke->hash_table =
-               kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL);
-       if (!journal->j_revoke->hash_table) {
-               kfree(journal->j_revoke_table[0]->hash_table);
-               kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[0]);
-               kmem_cache_free(jbd2_revoke_table_cache, journal->j_revoke_table[1]);
-               journal->j_revoke = NULL;
-               return -ENOMEM;
-       }
+       journal->j_revoke_table[1] = jbd2_journal_init_revoke_table(hash_size);
+       if (!journal->j_revoke_table[1])
+               goto fail1;
 
-       for (tmp = 0; tmp < hash_size; tmp++)
-               INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
+       journal->j_revoke = journal->j_revoke_table[1];
 
        spin_lock_init(&journal->j_revoke_lock);
 
        return 0;
-}
 
-/* Destoy a journal's revoke table.  The table must already be empty! */
+fail1:
+       jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]);
+fail0:
+       return -ENOMEM;
+}
 
+/* Destroy a journal's revoke table.  The table must already be empty! */
 void jbd2_journal_destroy_revoke(journal_t *journal)
 {
-       struct jbd2_revoke_table_s *table;
-       struct list_head *hash_list;
-       int i;
-
-       table = journal->j_revoke_table[0];
-       if (!table)
-               return;
-
-       for (i=0; i<table->hash_size; i++) {
-               hash_list = &table->hash_table[i];
-               J_ASSERT (list_empty(hash_list));
-       }
-
-       kfree(table->hash_table);
-       kmem_cache_free(jbd2_revoke_table_cache, table);
-       journal->j_revoke = NULL;
-
-       table = journal->j_revoke_table[1];
-       if (!table)
-               return;
-
-       for (i=0; i<table->hash_size; i++) {
-               hash_list = &table->hash_table[i];
-               J_ASSERT (list_empty(hash_list));
-       }
-
-       kfree(table->hash_table);
-       kmem_cache_free(jbd2_revoke_table_cache, table);
        journal->j_revoke = NULL;
+       if (journal->j_revoke_table[0])
+               jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]);
+       if (journal->j_revoke_table[1])
+               jbd2_journal_destroy_revoke_table(journal->j_revoke_table[1]);
 }
 
 
index b9b0b6f899b91b2000cc4f34e72c97931670fe53..d6e006e67804d5facfbad041797e87586266751b 100644 (file)
@@ -617,6 +617,12 @@ repeat:
            jh->b_next_transaction == transaction)
                goto done;
 
+       /*
+        * this is the first time this transaction is touching this buffer,
+        * reset the modified flag
+        */
+       jh->b_modified = 0;
+
        /*
         * If there is already a copy-out version of this buffer, then we don't
         * need to make another one
@@ -690,7 +696,7 @@ repeat:
                                if (!frozen_buffer) {
                                        printk(KERN_EMERG
                                               "%s: OOM for frozen_buffer\n",
-                                              __FUNCTION__);
+                                              __func__);
                                        JBUFFER_TRACE(jh, "oom!");
                                        error = -ENOMEM;
                                        jbd_lock_bh_state(bh);
@@ -829,9 +835,16 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh)
 
        if (jh->b_transaction == NULL) {
                jh->b_transaction = transaction;
+
+               /* first access by this transaction */
+               jh->b_modified = 0;
+
                JBUFFER_TRACE(jh, "file as BJ_Reserved");
                __jbd2_journal_file_buffer(jh, transaction, BJ_Reserved);
        } else if (jh->b_transaction == journal->j_committing_transaction) {
+               /* first access by this transaction */
+               jh->b_modified = 0;
+
                JBUFFER_TRACE(jh, "set next transaction");
                jh->b_next_transaction = transaction;
        }
@@ -901,7 +914,7 @@ repeat:
                committed_data = jbd2_alloc(jh2bh(jh)->b_size, GFP_NOFS);
                if (!committed_data) {
                        printk(KERN_EMERG "%s: No memory for committed data\n",
-                               __FUNCTION__);
+                               __func__);
                        err = -ENOMEM;
                        goto out;
                }
@@ -1230,6 +1243,7 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
        struct journal_head *jh;
        int drop_reserve = 0;
        int err = 0;
+       int was_modified = 0;
 
        BUFFER_TRACE(bh, "entry");
 
@@ -1248,6 +1262,9 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
                goto not_jbd;
        }
 
+       /* keep track of wether or not this transaction modified us */
+       was_modified = jh->b_modified;
+
        /*
         * The buffer's going from the transaction, we must drop
         * all references -bzzz
@@ -1265,7 +1282,12 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
 
                JBUFFER_TRACE(jh, "belongs to current transaction: unfile");
 
-               drop_reserve = 1;
+               /*
+                * we only want to drop a reference if this transaction
+                * modified the buffer
+                */
+               if (was_modified)
+                       drop_reserve = 1;
 
                /*
                 * We are no longer going to journal this buffer.
@@ -1305,7 +1327,13 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
                if (jh->b_next_transaction) {
                        J_ASSERT(jh->b_next_transaction == transaction);
                        jh->b_next_transaction = NULL;
-                       drop_reserve = 1;
+
+                       /*
+                        * only drop a reference if this transaction modified
+                        * the buffer
+                        */
+                       if (was_modified)
+                               drop_reserve = 1;
                }
        }
 
@@ -1434,7 +1462,8 @@ int jbd2_journal_stop(handle_t *handle)
        return err;
 }
 
-/**int jbd2_journal_force_commit() - force any uncommitted transactions
+/**
+ * int jbd2_journal_force_commit() - force any uncommitted transactions
  * @journal: journal to force
  *
  * For synchronous operations: force any uncommitted transactions
@@ -2077,7 +2106,7 @@ void __jbd2_journal_refile_buffer(struct journal_head *jh)
        jh->b_transaction = jh->b_next_transaction;
        jh->b_next_transaction = NULL;
        __jbd2_journal_file_buffer(jh, jh->b_transaction,
-                               was_dirty ? BJ_Metadata : BJ_Reserved);
+                               jh->b_modified ? BJ_Metadata : BJ_Reserved);
        J_ASSERT_JH(jh, jh->b_transaction->t_state == T_RUNNING);
 
        if (was_dirty)
index 9645275023e68c5b93f582a10d31d541a4a79884..a113ecc3bafeeb5f74172d8d5eb98e09f6eb6979 100644 (file)
        do {                                                            \
                printk(JFFS2_ERR_MSG_PREFIX                             \
                        " (%d) %s: " fmt, task_pid_nr(current),         \
-                       __FUNCTION__ , ##__VA_ARGS__);                  \
+                       __func__ , ##__VA_ARGS__);                      \
        } while(0)
 
 #define JFFS2_WARNING(fmt, ...)                                                \
        do {                                                            \
                printk(JFFS2_WARN_MSG_PREFIX                            \
                        " (%d) %s: " fmt, task_pid_nr(current),         \
-                       __FUNCTION__ , ##__VA_ARGS__);                  \
+                       __func__ , ##__VA_ARGS__);                      \
        } while(0)
 
 #define JFFS2_NOTICE(fmt, ...)                                         \
        do {                                                            \
                printk(JFFS2_NOTICE_MSG_PREFIX                          \
                        " (%d) %s: " fmt, task_pid_nr(current),         \
-                       __FUNCTION__ , ##__VA_ARGS__);                  \
+                       __func__ , ##__VA_ARGS__);                      \
        } while(0)
 
 #define JFFS2_DEBUG(fmt, ...)                                          \
        do {                                                            \
                printk(JFFS2_DBG_MSG_PREFIX                             \
                        " (%d) %s: " fmt, task_pid_nr(current),         \
-                       __FUNCTION__ , ##__VA_ARGS__);                  \
+                       __func__ , ##__VA_ARGS__);                      \
        } while(0)
 
 /*
index e48665984cb3393d1f859e27db42ba29a6937345..574cb7532d6c13e8b0fa6b3e1ccc1638ebfc4201 100644 (file)
@@ -82,7 +82,7 @@ static int is_xattr_datum_unchecked(struct jffs2_sb_info *c, struct jffs2_xattr_
 static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
 {
        /* must be called under down_write(xattr_sem) */
-       D1(dbg_xattr("%s: xid=%u, version=%u\n", __FUNCTION__, xd->xid, xd->version));
+       D1(dbg_xattr("%s: xid=%u, version=%u\n", __func__, xd->xid, xd->version));
        if (xd->xname) {
                c->xdatum_mem_usage -= (xd->name_len + 1 + xd->value_len);
                kfree(xd->xname);
@@ -1252,7 +1252,7 @@ int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_
        rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE);
        if (rc) {
                JFFS2_WARNING("%s: jffs2_reserve_space_gc() = %d, request = %u\n",
-                             __FUNCTION__, rc, totlen);
+                             __func__, rc, totlen);
                rc = rc ? rc : -EBADFD;
                goto out;
        }
index 887f5759e53643bdba5086363d587d82a789c5d3..bf6ab19b86ee1e2766dad7165800c70897dde984 100644 (file)
@@ -89,7 +89,7 @@ void jfs_proc_init(void)
 {
        int i;
 
-       if (!(base = proc_mkdir("jfs", proc_root_fs)))
+       if (!(base = proc_mkdir("fs/jfs", NULL)))
                return;
        base->owner = THIS_MODULE;
 
@@ -109,7 +109,7 @@ void jfs_proc_clean(void)
        if (base) {
                for (i = 0; i < NPROCENT; i++)
                        remove_proc_entry(Entries[i].name, base);
-               remove_proc_entry("jfs", proc_root_fs);
+               remove_proc_entry("fs/jfs", NULL);
        }
 }
 
index 40b16f23e49af4eb99c8060d5e52aad370e0613c..5df517b81f3f2a7911e1518c33021e9eb557c85e 100644 (file)
@@ -573,7 +573,7 @@ again:
                /* Ensure the resulting lock will get added to granted list */
                fl->fl_flags |= FL_SLEEP;
                if (do_vfs_lock(fl) < 0)
-                       printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
+                       printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __func__);
                up_read(&host->h_rwsem);
                fl->fl_flags = fl_flags;
                status = 0;
index 4d81553d29485e69dd19e746a1edadf4618c8d91..81aca859bfde909f2574c2c7f9e9e02608a1a165 100644 (file)
@@ -752,7 +752,7 @@ nlmsvc_grant_blocked(struct nlm_block *block)
                return;
        default:
                printk(KERN_WARNING "lockd: unexpected error %d in %s!\n",
-                               -error, __FUNCTION__);
+                               -error, __func__);
                nlmsvc_insert_block(block, 10 * HZ);
                nlmsvc_release_block(block);
                return;
index 2d4358c59f681fc939206fb064f66284ea0d599e..05ff4f1d7026f4fbed45d09208c4b8cda3a0a72e 100644 (file)
@@ -609,7 +609,7 @@ error_inode:
        if (corrupt < 0) {
                fat_fs_panic(new_dir->i_sb,
                             "%s: Filesystem corrupted (i_pos %lld)",
-                            __FUNCTION__, sinfo.i_pos);
+                            __func__, sinfo.i_pos);
        }
        goto out;
 }
index e179f71bfcb058df613f83cb1ff923d47ffc4618..32fd9655485b7fc9b8c8616ad6a61f6ac243b328 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/capability.h>
 #include <linux/file.h>
 #include <linux/fcntl.h>
+#include <linux/device_cgroup.h>
 #include <asm/namei.h>
 #include <asm/uaccess.h>
 
@@ -281,6 +282,10 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
        if (retval)
                return retval;
 
+       retval = devcgroup_inode_permission(inode, mask);
+       if (retval)
+               return retval;
+
        return security_inode_permission(inode, mask, nd);
 }
 
@@ -2028,6 +2033,10 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
        if (!dir->i_op || !dir->i_op->mknod)
                return -EPERM;
 
+       error = devcgroup_inode_mknod(mode, dev);
+       if (error)
+               return error;
+
        error = security_inode_mknod(dir, dentry, mode, dev);
        if (error)
                return error;
index fe376805cf5f3d877d58c3ff03c103ca0538777d..4fc302c2a0e0f886e4026288bcdc50888ddf3551 100644 (file)
@@ -1176,17 +1176,6 @@ static int mount_is_safe(struct nameidata *nd)
 #endif
 }
 
-static int lives_below_in_same_fs(struct dentry *d, struct dentry *dentry)
-{
-       while (1) {
-               if (d == dentry)
-                       return 1;
-               if (d == NULL || d == d->d_parent)
-                       return 0;
-               d = d->d_parent;
-       }
-}
-
 struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
                                        int flag)
 {
@@ -1203,7 +1192,7 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
 
        p = mnt;
        list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) {
-               if (!lives_below_in_same_fs(r->mnt_mountpoint, dentry))
+               if (!is_subdir(r->mnt_mountpoint, dentry))
                        continue;
 
                for (s = r; s; s = next_mnt(s, r)) {
@@ -2340,10 +2329,10 @@ void __init mnt_init(void)
        err = sysfs_init();
        if (err)
                printk(KERN_WARNING "%s: sysfs_init error: %d\n",
-                       __FUNCTION__, err);
+                       __func__, err);
        fs_kobj = kobject_create_and_add("fs", NULL);
        if (!fs_kobj)
-               printk(KERN_WARNING "%s: kobj create error\n", __FUNCTION__);
+               printk(KERN_WARNING "%s: kobj create error\n", __func__);
        init_rootfs();
        init_mount_tree();
 }
index df6d60bdfcd3f0087a8bad1aed6707435ff8c2dc..97645f112114e0c2f1aa4304a1f85046ec66ebb6 100644 (file)
@@ -102,48 +102,47 @@ static inline void ncp_init_request_s(struct ncp_server *server, int subfunction
 }
 
 static inline char *
- ncp_reply_data(struct ncp_server *server, int offset)
+ncp_reply_data(struct ncp_server *server, int offset)
 {
        return &(server->packet[sizeof(struct ncp_reply_header) + offset]);
 }
 
-static inline __u8 BVAL(void* data)
+static inline u8 BVAL(void *data)
 {
-       return get_unaligned((__u8*)data);
+       return *(u8 *)data;
 }
 
-static __u8
- ncp_reply_byte(struct ncp_server *server, int offset)
+static u8 ncp_reply_byte(struct ncp_server *server, int offset)
 {
-       return get_unaligned((__u8 *) ncp_reply_data(server, offset));
+       return *(u8 *)ncp_reply_data(server, offset);
 }
 
-static inline __u16 WVAL_LH(void* data)
+static inline u16 WVAL_LH(void *data)
 {
-       return le16_to_cpu(get_unaligned((__le16*)data));
+       return get_unaligned_le16(data);
 }
 
-static __u16
- ncp_reply_le16(struct ncp_server *server, int offset)
+static u16
+ncp_reply_le16(struct ncp_server *server, int offset)
 {
-       return le16_to_cpu(get_unaligned((__le16 *) ncp_reply_data(server, offset)));
+       return get_unaligned_le16(ncp_reply_data(server, offset));
 }
 
-static __u16
- ncp_reply_be16(struct ncp_server *server, int offset)
+static u16
+ncp_reply_be16(struct ncp_server *server, int offset)
 {
-       return be16_to_cpu(get_unaligned((__be16 *) ncp_reply_data(server, offset)));
+       return get_unaligned_be16(ncp_reply_data(server, offset));
 }
 
-static inline __u32 DVAL_LH(void* data)
+static inline u32 DVAL_LH(void *data)
 {
-       return le32_to_cpu(get_unaligned((__le32*)data));
+       return get_unaligned_le32(data);
 }
 
 static __le32
- ncp_reply_dword(struct ncp_server *server, int offset)
+ncp_reply_dword(struct ncp_server *server, int offset)
 {
-       return get_unaligned((__le32 *) ncp_reply_data(server, offset));
+       return get_unaligned((__le32 *)ncp_reply_data(server, offset));
 }
 
 static inline __u32 ncp_reply_dword_lh(struct ncp_server* server, int offset) {
@@ -1006,8 +1005,8 @@ ncp_read_bounce(struct ncp_server *server, const char *file_id,
        result = ncp_request2(server, 72, bounce, bufsize);
        ncp_unlock_server(server);
        if (!result) {
-               int len = be16_to_cpu(get_unaligned((__be16*)((char*)bounce + 
-                         sizeof(struct ncp_reply_header))));
+               int len = get_unaligned_be16((char *)bounce +
+                         sizeof(struct ncp_reply_header));
                result = -EIO;
                if (len <= to_read) {
                        char* source;
index f2f3b284e6dd203a31c11032a195ecc9f6237f53..89ac5bb0401c243784925cef21199036558a2c0d 100644 (file)
@@ -1321,6 +1321,7 @@ static const struct file_operations nfs_server_list_fops = {
        .read           = seq_read,
        .llseek         = seq_lseek,
        .release        = seq_release,
+       .owner          = THIS_MODULE,
 };
 
 static int nfs_volume_list_open(struct inode *inode, struct file *file);
@@ -1341,6 +1342,7 @@ static const struct file_operations nfs_volume_list_fops = {
        .read           = seq_read,
        .llseek         = seq_lseek,
        .release        = seq_release,
+       .owner          = THIS_MODULE,
 };
 
 /*
@@ -1500,33 +1502,29 @@ int __init nfs_fs_proc_init(void)
 {
        struct proc_dir_entry *p;
 
-       proc_fs_nfs = proc_mkdir("nfsfs", proc_root_fs);
+       proc_fs_nfs = proc_mkdir("fs/nfsfs", NULL);
        if (!proc_fs_nfs)
                goto error_0;
 
        proc_fs_nfs->owner = THIS_MODULE;
 
        /* a file of servers with which we're dealing */
-       p = create_proc_entry("servers", S_IFREG|S_IRUGO, proc_fs_nfs);
+       p = proc_create("servers", S_IFREG|S_IRUGO,
+                       proc_fs_nfs, &nfs_server_list_fops);
        if (!p)
                goto error_1;
 
-       p->proc_fops = &nfs_server_list_fops;
-       p->owner = THIS_MODULE;
-
        /* a file of volumes that we have mounted */
-       p = create_proc_entry("volumes", S_IFREG|S_IRUGO, proc_fs_nfs);
+       p = proc_create("volumes", S_IFREG|S_IRUGO,
+                       proc_fs_nfs, &nfs_volume_list_fops);
        if (!p)
                goto error_2;
-
-       p->proc_fops = &nfs_volume_list_fops;
-       p->owner = THIS_MODULE;
        return 0;
 
 error_2:
        remove_proc_entry("servers", proc_fs_nfs);
 error_1:
-       remove_proc_entry("nfsfs", proc_root_fs);
+       remove_proc_entry("fs/nfsfs", NULL);
 error_0:
        return -ENOMEM;
 }
@@ -1538,7 +1536,7 @@ void nfs_fs_proc_exit(void)
 {
        remove_proc_entry("volumes", proc_fs_nfs);
        remove_proc_entry("servers", proc_fs_nfs);
-       remove_proc_entry("nfsfs", proc_root_fs);
+       remove_proc_entry("fs/nfsfs", NULL);
 }
 
 #endif /* CONFIG_PROC_FS */
index fa220dc74609abc1635bbc55b740bd523156ccf0..7226a506f3ca55ea587ece913ec8a64982ff64be 100644 (file)
@@ -1575,6 +1575,11 @@ static int nfs_compare_super(struct super_block *sb, void *data)
        return nfs_compare_mount_options(sb, server, mntflags);
 }
 
+static int nfs_bdi_register(struct nfs_server *server)
+{
+       return bdi_register_dev(&server->backing_dev_info, server->s_dev);
+}
+
 static int nfs_get_sb(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
 {
@@ -1617,6 +1622,10 @@ static int nfs_get_sb(struct file_system_type *fs_type,
        if (s->s_fs_info != server) {
                nfs_free_server(server);
                server = NULL;
+       } else {
+               error = nfs_bdi_register(server);
+               if (error)
+                       goto error_splat_super;
        }
 
        if (!s->s_root) {
@@ -1664,6 +1673,7 @@ static void nfs_kill_super(struct super_block *s)
 {
        struct nfs_server *server = NFS_SB(s);
 
+       bdi_unregister(&server->backing_dev_info);
        kill_anon_super(s);
        nfs_free_server(server);
 }
@@ -1708,6 +1718,10 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
        if (s->s_fs_info != server) {
                nfs_free_server(server);
                server = NULL;
+       } else {
+               error = nfs_bdi_register(server);
+               if (error)
+                       goto error_splat_super;
        }
 
        if (!s->s_root) {
@@ -1984,6 +1998,10 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
        if (s->s_fs_info != server) {
                nfs_free_server(server);
                server = NULL;
+       } else {
+               error = nfs_bdi_register(server);
+               if (error)
+                       goto error_splat_super;
        }
 
        if (!s->s_root) {
@@ -2070,6 +2088,10 @@ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
        if (s->s_fs_info != server) {
                nfs_free_server(server);
                server = NULL;
+       } else {
+               error = nfs_bdi_register(server);
+               if (error)
+                       goto error_splat_super;
        }
 
        if (!s->s_root) {
@@ -2149,6 +2171,10 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags,
        if (s->s_fs_info != server) {
                nfs_free_server(server);
                server = NULL;
+       } else {
+               error = nfs_bdi_register(server);
+               if (error)
+                       goto error_splat_super;
        }
 
        if (!s->s_root) {
index 562abf3380d032e96342589fa13232233698c130..0b3ffa9840c20e0530ee4f9de9aa423cb813fc52 100644 (file)
@@ -104,7 +104,7 @@ xdr_writemem(__be32 *p, const void *ptr, int nbytes)
 } while (0)
 #define RESERVE_SPACE(nbytes)   do {                            \
        p = xdr_reserve_space(xdr, nbytes);                     \
-       if (!p) dprintk("NFSD: RESERVE_SPACE(%d) failed in function %s\n", (int) (nbytes), __FUNCTION__); \
+       if (!p) dprintk("NFSD: RESERVE_SPACE(%d) failed in function %s\n", (int) (nbytes), __func__); \
        BUG_ON(!p);                                             \
 } while (0)
 
@@ -134,7 +134,7 @@ xdr_error:                                      \
        p = xdr_inline_decode(xdr, nbytes); \
        if (!p) { \
                dprintk("NFSD: %s: reply buffer overflowed in line %d.\n", \
-                       __FUNCTION__, __LINE__); \
+                       __func__, __LINE__); \
                return -EIO; \
        } \
 } while (0)
index 42f3820ee8f543ca022d019b3b1de49e5907648c..5ac00c4fee919c220bee1fb2dc4c964742b079f5 100644 (file)
@@ -169,6 +169,7 @@ static const struct file_operations exports_operations = {
        .read           = seq_read,
        .llseek         = seq_lseek,
        .release        = seq_release,
+       .owner          = THIS_MODULE,
 };
 
 /*----------------------------------------------------------------------------*/
@@ -801,10 +802,9 @@ static int create_proc_exports_entry(void)
        entry = proc_mkdir("fs/nfs", NULL);
        if (!entry)
                return -ENOMEM;
-       entry = create_proc_entry("fs/nfs/exports", 0, NULL);
+       entry = proc_create("exports", 0, entry, &exports_operations);
        if (!entry)
                return -ENOMEM;
-       entry->proc_fops =  &exports_operations;
        return 0;
 }
 #else /* CONFIG_PROC_FS */
index 8ac37c33d1278ef7d602e5dd3aa57de98e1d2236..5e6724c1afd1d0276d7e839c9bfcbd2832fbd600 100644 (file)
@@ -45,7 +45,7 @@ static void ntfs_debug(const char *f, ...);
 extern void __ntfs_debug (const char *file, int line, const char *function,
        const char *format, ...) __attribute__ ((format (printf, 4, 5)));
 #define ntfs_debug(f, a...)                                            \
-       __ntfs_debug(__FILE__, __LINE__, __FUNCTION__, f, ##a)
+       __ntfs_debug(__FILE__, __LINE__, __func__, f, ##a)
 
 extern void ntfs_debug_dump_runlist(const runlist_element *rl);
 
@@ -58,10 +58,10 @@ extern void ntfs_debug_dump_runlist(const runlist_element *rl);
 
 extern void __ntfs_warning(const char *function, const struct super_block *sb,
                const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
-#define ntfs_warning(sb, f, a...)      __ntfs_warning(__FUNCTION__, sb, f, ##a)
+#define ntfs_warning(sb, f, a...)      __ntfs_warning(__func__, sb, f, ##a)
 
 extern void __ntfs_error(const char *function, const struct super_block *sb,
                const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
-#define ntfs_error(sb, f, a...)                __ntfs_error(__FUNCTION__, sb, f, ##a)
+#define ntfs_error(sb, f, a...)                __ntfs_error(__func__, sb, f, ##a)
 
 #endif /* _LINUX_NTFS_DEBUG_H */
index 2ad5c8b104b934c9177e162d2c20c6da211ed0d9..790defb847e71786e8b34358a11ccf5dfe1e0609 100644 (file)
@@ -1191,7 +1191,7 @@ static int ntfs_mft_bitmap_find_and_alloc_free_rec_nolock(ntfs_volume *vol,
                if (size) {
                        page = ntfs_map_page(mftbmp_mapping,
                                        ofs >> PAGE_CACHE_SHIFT);
-                       if (unlikely(IS_ERR(page))) {
+                       if (IS_ERR(page)) {
                                ntfs_error(vol->sb, "Failed to read mft "
                                                "bitmap, aborting.");
                                return PTR_ERR(page);
@@ -2118,7 +2118,7 @@ static int ntfs_mft_record_format(const ntfs_volume *vol, const s64 mft_no)
        }
        /* Read, map, and pin the page containing the mft record. */
        page = ntfs_map_page(mft_vi->i_mapping, index);
-       if (unlikely(IS_ERR(page))) {
+       if (IS_ERR(page)) {
                ntfs_error(vol->sb, "Failed to map page containing mft record "
                                "to format 0x%llx.", (long long)mft_no);
                return PTR_ERR(page);
@@ -2519,7 +2519,7 @@ mft_rec_already_initialized:
        ofs = (bit << vol->mft_record_size_bits) & ~PAGE_CACHE_MASK;
        /* Read, map, and pin the page containing the mft record. */
        page = ntfs_map_page(vol->mft_ino->i_mapping, index);
-       if (unlikely(IS_ERR(page))) {
+       if (IS_ERR(page)) {
                ntfs_error(vol->sb, "Failed to map page containing allocated "
                                "mft record 0x%llx.", (long long)bit);
                err = PTR_ERR(page);
index 61a000f8524c7aab2785a0c487c1ebe5d5fadf0a..e48aba698b775a895d32c87b254dc54fe5b2006f 100644 (file)
@@ -327,7 +327,7 @@ clear_fields:
 
 static struct backing_dev_info dlmfs_backing_dev_info = {
        .ra_pages       = 0,    /* No readahead */
-       .capabilities   = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
+       .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK,
 };
 
 static struct inode *dlmfs_get_root_inode(struct super_block *sb)
index e7dd1d4e34734c6c139dbd1f8486becaa418a166..0fdda2e8a4cc916648b035a1f962eaf8744797fa 100644 (file)
 #ifndef CONFIG_LDM_DEBUG
 #define ldm_debug(...) do {} while (0)
 #else
-#define ldm_debug(f, a...) _ldm_printk (KERN_DEBUG, __FUNCTION__, f, ##a)
+#define ldm_debug(f, a...) _ldm_printk (KERN_DEBUG, __func__, f, ##a)
 #endif
 
-#define ldm_crit(f, a...)  _ldm_printk (KERN_CRIT,  __FUNCTION__, f, ##a)
-#define ldm_error(f, a...) _ldm_printk (KERN_ERR,   __FUNCTION__, f, ##a)
-#define ldm_info(f, a...)  _ldm_printk (KERN_INFO,  __FUNCTION__, f, ##a)
+#define ldm_crit(f, a...)  _ldm_printk (KERN_CRIT,  __func__, f, ##a)
+#define ldm_error(f, a...) _ldm_printk (KERN_ERR,   __func__, f, ##a)
+#define ldm_info(f, a...)  _ldm_printk (KERN_INFO,  __func__, f, ##a)
 
 __attribute__ ((format (printf, 3, 4)))
 static void _ldm_printk (const char *level, const char *function,
index 07d6c4853fe858da49c51d8c199a8a3ff635602a..c135cbdd9127a550d6da103f66fa7cc47584b72e 100644 (file)
@@ -425,12 +425,13 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
        cutime = cstime = utime = stime = cputime_zero;
        cgtime = gtime = cputime_zero;
 
-       rcu_read_lock();
        if (lock_task_sighand(task, &flags)) {
                struct signal_struct *sig = task->signal;
 
                if (sig->tty) {
-                       tty_pgrp = pid_nr_ns(sig->tty->pgrp, ns);
+                       struct pid *pgrp = tty_get_pgrp(sig->tty);
+                       tty_pgrp = pid_nr_ns(pgrp, ns);
+                       put_pid(pgrp);
                        tty_nr = new_encode_dev(tty_devnum(sig->tty));
                }
 
@@ -469,7 +470,6 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
 
                unlock_task_sighand(task, &flags);
        }
-       rcu_read_unlock();
 
        if (!whole || num_threads < 2)
                wchan = get_wchan(task);
index c5e412a00b170e5294964505726b85f6cff93309..fcf02f2deeba398f790a4657574cfcbed9b55bc9 100644 (file)
@@ -195,12 +195,32 @@ static int proc_root_link(struct inode *inode, struct path *path)
        return result;
 }
 
-#define MAY_PTRACE(task) \
-       (task == current || \
-       (task->parent == current && \
-       (task->ptrace & PT_PTRACED) && \
-        (task_is_stopped_or_traced(task)) && \
-        security_ptrace(current,task) == 0))
+/*
+ * Return zero if current may access user memory in @task, -error if not.
+ */
+static int check_mem_permission(struct task_struct *task)
+{
+       /*
+        * A task can always look at itself, in case it chooses
+        * to use system calls instead of load instructions.
+        */
+       if (task == current)
+               return 0;
+
+       /*
+        * If current is actively ptrace'ing, and would also be
+        * permitted to freshly attach with ptrace now, permit it.
+        */
+       if (task->parent == current && (task->ptrace & PT_PTRACED) &&
+           task_is_stopped_or_traced(task) &&
+           ptrace_may_attach(task))
+               return 0;
+
+       /*
+        * Noone else is allowed.
+        */
+       return -EPERM;
+}
 
 struct mm_struct *mm_for_maps(struct task_struct *task)
 {
@@ -722,7 +742,7 @@ static ssize_t mem_read(struct file * file, char __user * buf,
        if (!task)
                goto out_no_task;
 
-       if (!MAY_PTRACE(task) || !ptrace_may_attach(task))
+       if (check_mem_permission(task))
                goto out;
 
        ret = -ENOMEM;
@@ -748,7 +768,7 @@ static ssize_t mem_read(struct file * file, char __user * buf,
 
                this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
                retval = access_process_vm(task, src, page, this_len, 0);
-               if (!retval || !MAY_PTRACE(task) || !ptrace_may_attach(task)) {
+               if (!retval || check_mem_permission(task)) {
                        if (!ret)
                                ret = -EIO;
                        break;
@@ -792,7 +812,7 @@ static ssize_t mem_write(struct file * file, const char __user *buf,
        if (!task)
                goto out_no_task;
 
-       if (!MAY_PTRACE(task) || !ptrace_may_attach(task))
+       if (check_mem_permission(task))
                goto out;
 
        copied = -ENOMEM;
@@ -1181,6 +1201,81 @@ static const struct file_operations proc_pid_sched_operations = {
 
 #endif
 
+/*
+ * We added or removed a vma mapping the executable. The vmas are only mapped
+ * during exec and are not mapped with the mmap system call.
+ * Callers must hold down_write() on the mm's mmap_sem for these
+ */
+void added_exe_file_vma(struct mm_struct *mm)
+{
+       mm->num_exe_file_vmas++;
+}
+
+void removed_exe_file_vma(struct mm_struct *mm)
+{
+       mm->num_exe_file_vmas--;
+       if ((mm->num_exe_file_vmas == 0) && mm->exe_file){
+               fput(mm->exe_file);
+               mm->exe_file = NULL;
+       }
+
+}
+
+void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file)
+{
+       if (new_exe_file)
+               get_file(new_exe_file);
+       if (mm->exe_file)
+               fput(mm->exe_file);
+       mm->exe_file = new_exe_file;
+       mm->num_exe_file_vmas = 0;
+}
+
+struct file *get_mm_exe_file(struct mm_struct *mm)
+{
+       struct file *exe_file;
+
+       /* We need mmap_sem to protect against races with removal of
+        * VM_EXECUTABLE vmas */
+       down_read(&mm->mmap_sem);
+       exe_file = mm->exe_file;
+       if (exe_file)
+               get_file(exe_file);
+       up_read(&mm->mmap_sem);
+       return exe_file;
+}
+
+void dup_mm_exe_file(struct mm_struct *oldmm, struct mm_struct *newmm)
+{
+       /* It's safe to write the exe_file pointer without exe_file_lock because
+        * this is called during fork when the task is not yet in /proc */
+       newmm->exe_file = get_mm_exe_file(oldmm);
+}
+
+static int proc_exe_link(struct inode *inode, struct path *exe_path)
+{
+       struct task_struct *task;
+       struct mm_struct *mm;
+       struct file *exe_file;
+
+       task = get_proc_task(inode);
+       if (!task)
+               return -ENOENT;
+       mm = get_task_mm(task);
+       put_task_struct(task);
+       if (!mm)
+               return -ENOENT;
+       exe_file = get_mm_exe_file(mm);
+       mmput(mm);
+       if (exe_file) {
+               *exe_path = exe_file->f_path;
+               path_get(&exe_file->f_path);
+               fput(exe_file);
+               return 0;
+       } else
+               return -ENOENT;
+}
+
 static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct inode *inode = dentry->d_inode;
index a36ad3c75cf43bbc0cb9f34d550893d952316ac1..9d53b39a9cf8983b8c2e30b9bc1c661dfe89f1b6 100644 (file)
@@ -69,12 +69,7 @@ proc_file_read(struct file *file, char __user *buf, size_t nbytes,
                count = min_t(size_t, PROC_BLOCK_SIZE, nbytes);
 
                start = NULL;
-               if (dp->get_info) {
-                       /* Handle old net routines */
-                       n = dp->get_info(page, &start, *ppos, count);
-                       if (n < count)
-                               eof = 1;
-               } else if (dp->read_proc) {
+               if (dp->read_proc) {
                        /*
                         * How to be a proc read function
                         * ------------------------------
@@ -277,8 +272,11 @@ static int xlate_proc_name(const char *name,
        int                     len;
        int                     rtn = 0;
 
+       de = *ret;
+       if (!de)
+               de = &proc_root;
+
        spin_lock(&proc_subdir_lock);
-       de = &proc_root;
        while (1) {
                next = strchr(cp, '/');
                if (!next)
@@ -385,20 +383,18 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir,
 
        lock_kernel();
        spin_lock(&proc_subdir_lock);
-       if (de) {
-               for (de = de->subdir; de ; de = de->next) {
-                       if (de->namelen != dentry->d_name.len)
-                               continue;
-                       if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
-                               unsigned int ino;
+       for (de = de->subdir; de ; de = de->next) {
+               if (de->namelen != dentry->d_name.len)
+                       continue;
+               if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
+                       unsigned int ino;
 
-                               ino = de->low_ino;
-                               de_get(de);
-                               spin_unlock(&proc_subdir_lock);
-                               error = -EINVAL;
-                               inode = proc_get_inode(dir->i_sb, ino, de);
-                               goto out_unlock;
-                       }
+                       ino = de->low_ino;
+                       de_get(de);
+                       spin_unlock(&proc_subdir_lock);
+                       error = -EINVAL;
+                       inode = proc_get_inode(dir->i_sb, ino, de);
+                       goto out_unlock;
                }
        }
        spin_unlock(&proc_subdir_lock);
@@ -410,7 +406,8 @@ out_unlock:
                d_add(dentry, inode);
                return NULL;
        }
-       de_put(de);
+       if (de)
+               de_put(de);
        return ERR_PTR(error);
 }
 
@@ -440,10 +437,6 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent,
        lock_kernel();
 
        ino = inode->i_ino;
-       if (!de) {
-               ret = -EINVAL;
-               goto out;
-       }
        i = filp->f_pos;
        switch (i) {
                case 0:
@@ -582,7 +575,7 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
        /* make sure name is valid */
        if (!name || !strlen(name)) goto out;
 
-       if (!(*parent) && xlate_proc_name(name, parent, &fn) != 0)
+       if (xlate_proc_name(name, parent, &fn) != 0)
                goto out;
 
        /* At this point there must not be any '/' characters beyond *fn */
@@ -682,9 +675,10 @@ struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
        return ent;
 }
 
-struct proc_dir_entry *proc_create(const char *name, mode_t mode,
-                                  struct proc_dir_entry *parent,
-                                  const struct file_operations *proc_fops)
+struct proc_dir_entry *proc_create_data(const char *name, mode_t mode,
+                                       struct proc_dir_entry *parent,
+                                       const struct file_operations *proc_fops,
+                                       void *data)
 {
        struct proc_dir_entry *pde;
        nlink_t nlink;
@@ -705,6 +699,7 @@ struct proc_dir_entry *proc_create(const char *name, mode_t mode,
        if (!pde)
                goto out;
        pde->proc_fops = proc_fops;
+       pde->data = data;
        if (proc_register(parent, pde) < 0)
                goto out_free;
        return pde;
@@ -734,55 +729,58 @@ void free_proc_entry(struct proc_dir_entry *de)
 void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
 {
        struct proc_dir_entry **p;
-       struct proc_dir_entry *de;
+       struct proc_dir_entry *de = NULL;
        const char *fn = name;
        int len;
 
-       if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
-               goto out;
+       if (xlate_proc_name(name, &parent, &fn) != 0)
+               return;
        len = strlen(fn);
 
        spin_lock(&proc_subdir_lock);
        for (p = &parent->subdir; *p; p=&(*p)->next ) {
-               if (!proc_match(len, fn, *p))
-                       continue;
-               de = *p;
-               *p = de->next;
-               de->next = NULL;
-
-               spin_lock(&de->pde_unload_lock);
-               /*
-                * Stop accepting new callers into module. If you're
-                * dynamically allocating ->proc_fops, save a pointer somewhere.
-                */
-               de->proc_fops = NULL;
-               /* Wait until all existing callers into module are done. */
-               if (de->pde_users > 0) {
-                       DECLARE_COMPLETION_ONSTACK(c);
-
-                       if (!de->pde_unload_completion)
-                               de->pde_unload_completion = &c;
-
-                       spin_unlock(&de->pde_unload_lock);
-                       spin_unlock(&proc_subdir_lock);
+               if (proc_match(len, fn, *p)) {
+                       de = *p;
+                       *p = de->next;
+                       de->next = NULL;
+                       break;
+               }
+       }
+       spin_unlock(&proc_subdir_lock);
+       if (!de)
+               return;
 
-                       wait_for_completion(de->pde_unload_completion);
+       spin_lock(&de->pde_unload_lock);
+       /*
+        * Stop accepting new callers into module. If you're
+        * dynamically allocating ->proc_fops, save a pointer somewhere.
+        */
+       de->proc_fops = NULL;
+       /* Wait until all existing callers into module are done. */
+       if (de->pde_users > 0) {
+               DECLARE_COMPLETION_ONSTACK(c);
+
+               if (!de->pde_unload_completion)
+                       de->pde_unload_completion = &c;
 
-                       spin_lock(&proc_subdir_lock);
-                       goto continue_removing;
-               }
                spin_unlock(&de->pde_unload_lock);
 
+               wait_for_completion(de->pde_unload_completion);
+
+               goto continue_removing;
+       }
+       spin_unlock(&de->pde_unload_lock);
+
 continue_removing:
-               if (S_ISDIR(de->mode))
-                       parent->nlink--;
-               de->nlink = 0;
-               WARN_ON(de->subdir);
-               if (atomic_dec_and_test(&de->count))
-                       free_proc_entry(de);
-               break;
+       if (S_ISDIR(de->mode))
+               parent->nlink--;
+       de->nlink = 0;
+       if (de->subdir) {
+               printk(KERN_WARNING "%s: removing non-empty directory "
+                       "'%s/%s', leaking at least '%s'\n", __func__,
+                       de->parent->name, de->name, de->subdir->name);
+               WARN_ON(1);
        }
-       spin_unlock(&proc_subdir_lock);
-out:
-       return;
+       if (atomic_dec_and_test(&de->count))
+               free_proc_entry(de);
 }
index 82b3a1b5a70b8c887a2e4b7cf698843097b84c0e..6f4e8dc97da1f24f6313b4425efa323fe82a644c 100644 (file)
@@ -25,8 +25,7 @@
 
 struct proc_dir_entry *de_get(struct proc_dir_entry *de)
 {
-       if (de)
-               atomic_inc(&de->count);
+       atomic_inc(&de->count);
        return de;
 }
 
@@ -35,18 +34,16 @@ struct proc_dir_entry *de_get(struct proc_dir_entry *de)
  */
 void de_put(struct proc_dir_entry *de)
 {
-       if (de) {       
-               lock_kernel();          
-               if (!atomic_read(&de->count)) {
-                       printk("de_put: entry %s already free!\n", de->name);
-                       unlock_kernel();
-                       return;
-               }
-
-               if (atomic_dec_and_test(&de->count))
-                       free_proc_entry(de);
+       lock_kernel();
+       if (!atomic_read(&de->count)) {
+               printk("de_put: entry %s already free!\n", de->name);
                unlock_kernel();
+               return;
        }
+
+       if (atomic_dec_and_test(&de->count))
+               free_proc_entry(de);
+       unlock_kernel();
 }
 
 /*
@@ -392,7 +389,7 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
 {
        struct inode * inode;
 
-       if (de != NULL && !try_module_get(de->owner))
+       if (!try_module_get(de->owner))
                goto out_mod;
 
        inode = iget_locked(sb, ino);
@@ -402,30 +399,29 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
                inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
                PROC_I(inode)->fd = 0;
                PROC_I(inode)->pde = de;
-               if (de) {
-                       if (de->mode) {
-                               inode->i_mode = de->mode;
-                               inode->i_uid = de->uid;
-                               inode->i_gid = de->gid;
-                       }
-                       if (de->size)
-                               inode->i_size = de->size;
-                       if (de->nlink)
-                               inode->i_nlink = de->nlink;
-                       if (de->proc_iops)
-                               inode->i_op = de->proc_iops;
-                       if (de->proc_fops) {
-                               if (S_ISREG(inode->i_mode)) {
+
+               if (de->mode) {
+                       inode->i_mode = de->mode;
+                       inode->i_uid = de->uid;
+                       inode->i_gid = de->gid;
+               }
+               if (de->size)
+                       inode->i_size = de->size;
+               if (de->nlink)
+                       inode->i_nlink = de->nlink;
+               if (de->proc_iops)
+                       inode->i_op = de->proc_iops;
+               if (de->proc_fops) {
+                       if (S_ISREG(inode->i_mode)) {
 #ifdef CONFIG_COMPAT
-                                       if (!de->proc_fops->compat_ioctl)
-                                               inode->i_fop =
-                                                       &proc_reg_file_ops_no_compat;
-                                       else
+                               if (!de->proc_fops->compat_ioctl)
+                                       inode->i_fop =
+                                               &proc_reg_file_ops_no_compat;
+                               else
 #endif
-                                               inode->i_fop = &proc_reg_file_ops;
-                               } else {
-                                       inode->i_fop = de->proc_fops;
-                               }
+                                       inode->i_fop = &proc_reg_file_ops;
+                       } else {
+                               inode->i_fop = de->proc_fops;
                        }
                }
                unlock_new_inode(inode);
@@ -433,8 +429,7 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
        return inode;
 
 out_ino:
-       if (de != NULL)
-               module_put(de->owner);
+       module_put(de->owner);
 out_mod:
        return NULL;
 }                      
index bc72f5c8c47d34704cb6a76ef450e1bd6dc84f0d..28cbca8059057e5f1b7729b69743aea11cecc27c 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/proc_fs.h>
 
+extern struct proc_dir_entry proc_root;
 #ifdef CONFIG_PROC_SYSCTL
 extern int proc_sys_init(void);
 #else
@@ -46,9 +47,6 @@ extern int nommu_vma_show(struct seq_file *, struct vm_area_struct *);
 
 extern int maps_protect;
 
-extern void create_seq_entry(char *name, mode_t mode,
-                               const struct file_operations *f);
-extern int proc_exe_link(struct inode *, struct path *);
 extern int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns,
                                struct pid *pid, struct task_struct *task);
 extern int proc_tgid_stat(struct seq_file *m, struct pid_namespace *ns,
index 941e95114b5a3bb3f248f41e15652da2f06ad0fa..79ecd281d2cbf1e1db1484ffe4b24413bc6f9e63 100644 (file)
@@ -137,7 +137,7 @@ static const struct file_operations proc_nommu_vma_list_operations = {
 
 static int __init proc_nommu_init(void)
 {
-       create_seq_entry("maps", S_IRUGO, &proc_nommu_vma_list_operations);
+       proc_create("maps", S_IRUGO, NULL, &proc_nommu_vma_list_operations);
        return 0;
 }
 
index 441a32f0e5f2f4460c243ad17ea29249bbd38728..74a323d2b850884f06c2206fc4d288e957c8bef6 100644 (file)
@@ -179,6 +179,7 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
                "PageTables:   %8lu kB\n"
                "NFS_Unstable: %8lu kB\n"
                "Bounce:       %8lu kB\n"
+               "WritebackTmp: %8lu kB\n"
                "CommitLimit:  %8lu kB\n"
                "Committed_AS: %8lu kB\n"
                "VmallocTotal: %8lu kB\n"
@@ -210,6 +211,7 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
                K(global_page_state(NR_PAGETABLE)),
                K(global_page_state(NR_UNSTABLE_NFS)),
                K(global_page_state(NR_BOUNCE)),
+               K(global_page_state(NR_WRITEBACK_TEMP)),
                K(allowed),
                K(committed),
                (unsigned long)VMALLOC_TOTAL >> 10,
@@ -826,14 +828,6 @@ static struct file_operations proc_kpageflags_operations = {
 
 struct proc_dir_entry *proc_root_kcore;
 
-void create_seq_entry(char *name, mode_t mode, const struct file_operations *f)
-{
-       struct proc_dir_entry *entry;
-       entry = create_proc_entry(name, mode, NULL);
-       if (entry)
-               entry->proc_fops = f;
-}
-
 void __init proc_misc_init(void)
 {
        static struct {
@@ -862,66 +856,52 @@ void __init proc_misc_init(void)
 
        /* And now for trickier ones */
 #ifdef CONFIG_PRINTK
-       {
-               struct proc_dir_entry *entry;
-               entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
-               if (entry)
-                       entry->proc_fops = &proc_kmsg_operations;
-       }
+       proc_create("kmsg", S_IRUSR, NULL, &proc_kmsg_operations);
 #endif
-       create_seq_entry("locks", 0, &proc_locks_operations);
-       create_seq_entry("devices", 0, &proc_devinfo_operations);
-       create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
+       proc_create("locks", 0, NULL, &proc_locks_operations);
+       proc_create("devices", 0, NULL, &proc_devinfo_operations);
+       proc_create("cpuinfo", 0, NULL, &proc_cpuinfo_operations);
 #ifdef CONFIG_BLOCK
-       create_seq_entry("partitions", 0, &proc_partitions_operations);
+       proc_create("partitions", 0, NULL, &proc_partitions_operations);
 #endif
-       create_seq_entry("stat", 0, &proc_stat_operations);
-       create_seq_entry("interrupts", 0, &proc_interrupts_operations);
+       proc_create("stat", 0, NULL, &proc_stat_operations);
+       proc_create("interrupts", 0, NULL, &proc_interrupts_operations);
 #ifdef CONFIG_SLABINFO
-       create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
+       proc_create("slabinfo",S_IWUSR|S_IRUGO,NULL,&proc_slabinfo_operations);
 #ifdef CONFIG_DEBUG_SLAB_LEAK
-       create_seq_entry("slab_allocators", 0 ,&proc_slabstats_operations);
+       proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations);
 #endif
 #endif
 #ifdef CONFIG_MMU
        proc_create("vmallocinfo", S_IRUSR, NULL, &proc_vmalloc_operations);
 #endif
-       create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
-       create_seq_entry("pagetypeinfo", S_IRUGO, &pagetypeinfo_file_ops);
-       create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
-       create_seq_entry("zoneinfo",S_IRUGO, &proc_zoneinfo_file_operations);
+       proc_create("buddyinfo", S_IRUGO, NULL, &fragmentation_file_operations);
+       proc_create("pagetypeinfo", S_IRUGO, NULL, &pagetypeinfo_file_ops);
+       proc_create("vmstat", S_IRUGO, NULL, &proc_vmstat_file_operations);
+       proc_create("zoneinfo", S_IRUGO, NULL, &proc_zoneinfo_file_operations);
 #ifdef CONFIG_BLOCK
-       create_seq_entry("diskstats", 0, &proc_diskstats_operations);
+       proc_create("diskstats", 0, NULL, &proc_diskstats_operations);
 #endif
 #ifdef CONFIG_MODULES
-       create_seq_entry("modules", 0, &proc_modules_operations);
+       proc_create("modules", 0, NULL, &proc_modules_operations);
 #endif
 #ifdef CONFIG_SCHEDSTATS
-       create_seq_entry("schedstat", 0, &proc_schedstat_operations);
+       proc_create("schedstat", 0, NULL, &proc_schedstat_operations);
 #endif
 #ifdef CONFIG_PROC_KCORE
-       proc_root_kcore = create_proc_entry("kcore", S_IRUSR, NULL);
-       if (proc_root_kcore) {
-               proc_root_kcore->proc_fops = &proc_kcore_operations;
+       proc_root_kcore = proc_create("kcore", S_IRUSR, NULL, &proc_kcore_operations);
+       if (proc_root_kcore)
                proc_root_kcore->size =
                                (size_t)high_memory - PAGE_OFFSET + PAGE_SIZE;
-       }
 #endif
 #ifdef CONFIG_PROC_PAGE_MONITOR
-       create_seq_entry("kpagecount", S_IRUSR, &proc_kpagecount_operations);
-       create_seq_entry("kpageflags", S_IRUSR, &proc_kpageflags_operations);
+       proc_create("kpagecount", S_IRUSR, NULL, &proc_kpagecount_operations);
+       proc_create("kpageflags", S_IRUSR, NULL, &proc_kpageflags_operations);
 #endif
 #ifdef CONFIG_PROC_VMCORE
-       proc_vmcore = create_proc_entry("vmcore", S_IRUSR, NULL);
-       if (proc_vmcore)
-               proc_vmcore->proc_fops = &proc_vmcore_operations;
+       proc_vmcore = proc_create("vmcore", S_IRUSR, NULL, &proc_vmcore_operations);
 #endif
 #ifdef CONFIG_MAGIC_SYSRQ
-       {
-               struct proc_dir_entry *entry;
-               entry = create_proc_entry("sysrq-trigger", S_IWUSR, NULL);
-               if (entry)
-                       entry->proc_fops = &proc_sysrq_trigger_operations;
-       }
+       proc_create("sysrq-trigger", S_IWUSR, NULL, &proc_sysrq_trigger_operations);
 #endif
 }
index 614c34b6d1c22214ffcdeb46a5f9e9eb63d69678..5acc001d49f6c72db83216173136701c2169f950 100644 (file)
@@ -165,8 +165,8 @@ out:
        return err;
 }
 
-static ssize_t proc_sys_read(struct file *filp, char __user *buf,
-                               size_t count, loff_t *ppos)
+static ssize_t proc_sys_call_handler(struct file *filp, void __user *buf,
+               size_t count, loff_t *ppos, int write)
 {
        struct dentry *dentry = filp->f_dentry;
        struct ctl_table_header *head;
@@ -190,12 +190,12 @@ static ssize_t proc_sys_read(struct file *filp, char __user *buf,
         * and won't be until we finish.
         */
        error = -EPERM;
-       if (sysctl_perm(table, MAY_READ))
+       if (sysctl_perm(head->root, table, write ? MAY_WRITE : MAY_READ))
                goto out;
 
        /* careful: calling conventions are nasty here */
        res = count;
-       error = table->proc_handler(table, 0, filp, buf, &res, ppos);
+       error = table->proc_handler(table, write, filp, buf, &res, ppos);
        if (!error)
                error = res;
 out:
@@ -204,44 +204,16 @@ out:
        return error;
 }
 
-static ssize_t proc_sys_write(struct file *filp, const char __user *buf,
+static ssize_t proc_sys_read(struct file *filp, char __user *buf,
                                size_t count, loff_t *ppos)
 {
-       struct dentry *dentry = filp->f_dentry;
-       struct ctl_table_header *head;
-       struct ctl_table *table;
-       ssize_t error;
-       size_t res;
-
-       table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head);
-       /* Has the sysctl entry disappeared on us? */
-       error = -ENOENT;
-       if (!table)
-               goto out;
-
-       /* Has the sysctl entry been replaced by a directory? */
-       error = -EISDIR;
-       if (!table->proc_handler)
-               goto out;
-
-       /*
-        * At this point we know that the sysctl was not unregistered
-        * and won't be until we finish.
-        */
-       error = -EPERM;
-       if (sysctl_perm(table, MAY_WRITE))
-               goto out;
-
-       /* careful: calling conventions are nasty here */
-       res = count;
-       error = table->proc_handler(table, 1, filp, (char __user *)buf,
-                                   &res, ppos);
-       if (!error)
-               error = res;
-out:
-       sysctl_head_finish(head);
+       return proc_sys_call_handler(filp, (void __user *)buf, count, ppos, 0);
+}
 
-       return error;
+static ssize_t proc_sys_write(struct file *filp, const char __user *buf,
+                               size_t count, loff_t *ppos)
+{
+       return proc_sys_call_handler(filp, (void __user *)buf, count, ppos, 1);
 }
 
 
@@ -416,7 +388,7 @@ static int proc_sys_permission(struct inode *inode, int mask, struct nameidata *
                goto out;
 
        /* Use the permissions on the sysctl table entry */
-       error = sysctl_perm(table, mask);
+       error = sysctl_perm(head->root, table, mask);
 out:
        sysctl_head_finish(head);
        return error;
index 49816e00b51a25899f860215166b97acd8584044..21f490f5d65ce1f96eb37095516eddb3c80aa4f8 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #include <asm/uaccess.h>
-
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/time.h>
@@ -136,39 +136,54 @@ static const struct file_operations proc_tty_drivers_operations = {
        .release        = seq_release,
 };
 
-/*
- * This is the handler for /proc/tty/ldiscs
- */
-static int tty_ldiscs_read_proc(char *page, char **start, off_t off,
-                               int count, int *eof, void *data)
+static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
 {
-       int     i;
-       int     len = 0;
-       off_t   begin = 0;
+       return (*pos < NR_LDISCS) ? pos : NULL;
+}
+
+static void * tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       (*pos)++;
+       return (*pos < NR_LDISCS) ? pos : NULL;
+}
+
+static void tty_ldiscs_seq_stop(struct seq_file *m, void *v)
+{
+}
+
+static int tty_ldiscs_seq_show(struct seq_file *m, void *v)
+{
+       int i = *(loff_t *)v;
        struct tty_ldisc *ld;
        
-       for (i=0; i < NR_LDISCS; i++) {
-               ld = tty_ldisc_get(i);
-               if (ld == NULL)
-                       continue;
-               len += sprintf(page+len, "%-10s %2d\n",
-                              ld->name ? ld->name : "???", i);
-               tty_ldisc_put(i);
-               if (len+begin > off+count)
-                       break;
-               if (len+begin < off) {
-                       begin += len;
-                       len = 0;
-               }
-       }
-       if (i >= NR_LDISCS)
-               *eof = 1;
-       if (off >= len+begin)
+       ld = tty_ldisc_get(i);
+       if (ld == NULL)
                return 0;
-       *start = page + (off-begin);
-       return ((count < begin+len-off) ? count : begin+len-off);
+       seq_printf(m, "%-10s %2d\n", ld->name ? ld->name : "???", i);
+       tty_ldisc_put(i);
+       return 0;
+}
+
+static const struct seq_operations tty_ldiscs_seq_ops = {
+       .start  = tty_ldiscs_seq_start,
+       .next   = tty_ldiscs_seq_next,
+       .stop   = tty_ldiscs_seq_stop,
+       .show   = tty_ldiscs_seq_show,
+};
+
+static int proc_tty_ldiscs_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &tty_ldiscs_seq_ops);
 }
 
+static const struct file_operations tty_ldiscs_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = proc_tty_ldiscs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
 /*
  * This function is called by tty_register_driver() to handle
  * registering the driver's /proc handler into /proc/tty/driver/<foo>
@@ -177,16 +192,14 @@ void proc_tty_register_driver(struct tty_driver *driver)
 {
        struct proc_dir_entry *ent;
                
-       if ((!driver->read_proc && !driver->write_proc) ||
-           !driver->driver_name ||
+       if (!driver->ops->read_proc || !driver->driver_name ||
            driver->proc_entry)
                return;
 
        ent = create_proc_entry(driver->driver_name, 0, proc_tty_driver);
        if (!ent)
                return;
-       ent->read_proc = driver->read_proc;
-       ent->write_proc = driver->write_proc;
+       ent->read_proc = driver->ops->read_proc;
        ent->owner = driver->owner;
        ent->data = driver;
 
@@ -214,7 +227,6 @@ void proc_tty_unregister_driver(struct tty_driver *driver)
  */
 void __init proc_tty_init(void)
 {
-       struct proc_dir_entry *entry;
        if (!proc_mkdir("tty", NULL))
                return;
        proc_tty_ldisc = proc_mkdir("tty/ldisc", NULL);
@@ -224,10 +236,7 @@ void __init proc_tty_init(void)
         * password lengths and inter-keystroke timings during password
         * entry.
         */
-       proc_tty_driver = proc_mkdir_mode("tty/driver", S_IRUSR | S_IXUSR, NULL);
-
-       create_proc_read_entry("tty/ldiscs", 0, NULL, tty_ldiscs_read_proc, NULL);
-       entry = create_proc_entry("tty/drivers", 0, NULL);
-       if (entry)
-               entry->proc_fops = &proc_tty_drivers_operations;
+       proc_tty_driver = proc_mkdir_mode("tty/driver", S_IRUSR|S_IXUSR, NULL);
+       proc_create("tty/ldiscs", 0, NULL, &tty_ldiscs_proc_fops);
+       proc_create("tty/drivers", 0, NULL, &proc_tty_drivers_operations);
 }
index ef0fb57fc9ef794e6a5b849c27efe26fadb9f4f8..95117538a4f6fd3b4fdc90558127caa282d7e800 100644 (file)
@@ -22,8 +22,6 @@
 
 #include "internal.h"
 
-struct proc_dir_entry *proc_bus, *proc_root_fs, *proc_root_driver;
-
 static int proc_test_super(struct super_block *sb, void *data)
 {
        return sb->s_fs_info == data;
@@ -126,8 +124,8 @@ void __init proc_root_init(void)
 #ifdef CONFIG_SYSVIPC
        proc_mkdir("sysvipc", NULL);
 #endif
-       proc_root_fs = proc_mkdir("fs", NULL);
-       proc_root_driver = proc_mkdir("driver", NULL);
+       proc_mkdir("fs", NULL);
+       proc_mkdir("driver", NULL);
        proc_mkdir("fs/nfsd", NULL); /* somewhere for the nfsd filesystem to be mounted */
 #if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
        /* just give it a mountpoint */
@@ -137,7 +135,7 @@ void __init proc_root_init(void)
 #ifdef CONFIG_PROC_DEVICETREE
        proc_device_tree_init();
 #endif
-       proc_bus = proc_mkdir("bus", NULL);
+       proc_mkdir("bus", NULL);
        proc_sys_init();
 }
 
@@ -232,9 +230,5 @@ void pid_ns_release_proc(struct pid_namespace *ns)
 EXPORT_SYMBOL(proc_symlink);
 EXPORT_SYMBOL(proc_mkdir);
 EXPORT_SYMBOL(create_proc_entry);
-EXPORT_SYMBOL(proc_create);
+EXPORT_SYMBOL(proc_create_data);
 EXPORT_SYMBOL(remove_proc_entry);
-EXPORT_SYMBOL(proc_root);
-EXPORT_SYMBOL(proc_root_fs);
-EXPORT_SYMBOL(proc_bus);
-EXPORT_SYMBOL(proc_root_driver);
index 7415eeb7cc3a75dda762e78052e49a77f6a509ff..e2b8e769f510d676997698b8fd28ef4346478d2c 100644 (file)
@@ -75,40 +75,6 @@ int task_statm(struct mm_struct *mm, int *shared, int *text,
        return mm->total_vm;
 }
 
-int proc_exe_link(struct inode *inode, struct path *path)
-{
-       struct vm_area_struct * vma;
-       int result = -ENOENT;
-       struct task_struct *task = get_proc_task(inode);
-       struct mm_struct * mm = NULL;
-
-       if (task) {
-               mm = get_task_mm(task);
-               put_task_struct(task);
-       }
-       if (!mm)
-               goto out;
-       down_read(&mm->mmap_sem);
-
-       vma = mm->mmap;
-       while (vma) {
-               if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
-                       break;
-               vma = vma->vm_next;
-       }
-
-       if (vma) {
-               *path = vma->vm_file->f_path;
-               path_get(&vma->vm_file->f_path);
-               result = 0;
-       }
-
-       up_read(&mm->mmap_sem);
-       mmput(mm);
-out:
-       return result;
-}
-
 static void pad_len_spaces(struct seq_file *m, int len)
 {
        len = 25 + sizeof(void*) * 6 - len;
index 8011528518bd7e73d022498466e79257bd2695ec..4b733f108455273ce52ce73c4f410d74a9ea2b2e 100644 (file)
@@ -103,40 +103,6 @@ int task_statm(struct mm_struct *mm, int *shared, int *text,
        return size;
 }
 
-int proc_exe_link(struct inode *inode, struct path *path)
-{
-       struct vm_list_struct *vml;
-       struct vm_area_struct *vma;
-       struct task_struct *task = get_proc_task(inode);
-       struct mm_struct *mm = get_task_mm(task);
-       int result = -ENOENT;
-
-       if (!mm)
-               goto out;
-       down_read(&mm->mmap_sem);
-
-       vml = mm->context.vmlist;
-       vma = NULL;
-       while (vml) {
-               if ((vml->vma->vm_flags & VM_EXECUTABLE) && vml->vma->vm_file) {
-                       vma = vml->vma;
-                       break;
-               }
-               vml = vml->next;
-       }
-
-       if (vma) {
-               *path = vma->vm_file->f_path;
-               path_get(&vma->vm_file->f_path);
-               result = 0;
-       }
-
-       up_read(&mm->mmap_sem);
-       mmput(mm);
-out:
-       return result;
-}
-
 /*
  * display mapping lines for a particular process's /proc/pid/maps
  */
index 23b647f25d08a405bad3ba8917d550f120d60ccf..234ada90363343ad668eff8213dd0927af7aa6f2 100644 (file)
@@ -306,7 +306,7 @@ static uint find_free_dqentry(struct dquot *dquot, int *err)
                        printk(KERN_ERR "VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n", blk);
                        goto out_buf;
                }
-       dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries)+1);
+       le16_add_cpu(&dh->dqdh_entries, 1);
        memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
        /* Find free structure in block */
        for (i = 0; i < V2_DQSTRINBLK && memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)); i++);
@@ -448,7 +448,7 @@ static int free_dqentry(struct dquot *dquot, uint blk)
                goto out_buf;
        }
        dh = (struct v2_disk_dqdbheader *)buf;
-       dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries)-1);
+       le16_add_cpu(&dh->dqdh_entries, -1);
        if (!le16_to_cpu(dh->dqdh_entries)) {   /* Block got free? */
                if ((ret = remove_free_dqentry(sb, type, buf, blk)) < 0 ||
                    (ret = put_free_dqblk(sb, type, buf, blk)) < 0) {
index b41a514b0976559a0f17f24bd98cdcea354b0c47..9590b90243002f084cc4a51e8b1bd25ca0cef8f4 100644 (file)
@@ -26,6 +26,9 @@
 
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/ramfs.h>
+
+#include "internal.h"
 
 const struct address_space_operations ramfs_aops = {
        .readpage       = simple_readpage,
index 8428d5b2711de8e901b75dd3c209039c3e2d429a..b13123424e49ce169da5c729c0e327fdf2259bf8 100644 (file)
@@ -44,7 +44,7 @@ static const struct inode_operations ramfs_dir_inode_operations;
 
 static struct backing_dev_info ramfs_backing_dev_info = {
        .ra_pages       = 0,    /* No readahead */
-       .capabilities   = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK |
+       .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK |
                          BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY |
                          BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP,
 };
index af7cc074a47621af7d160786515dec5280697f3c..6b330639b51dc7b497d6cc9ac8726ce0c004ec37 100644 (file)
@@ -11,5 +11,4 @@
 
 
 extern const struct address_space_operations ramfs_aops;
-extern const struct file_operations ramfs_file_operations;
 extern const struct inode_operations ramfs_file_inode_operations;
index da86042b3e03cd1b44f02af4d48c6e61174caf9b..e396b2fa4743e66b32d3ea4ad740aa403266fa40 100644 (file)
@@ -2574,11 +2574,9 @@ static int release_journal_dev(struct super_block *super,
 
        result = 0;
 
-       if (journal->j_dev_file != NULL) {
-               result = filp_close(journal->j_dev_file, NULL);
-               journal->j_dev_file = NULL;
-               journal->j_dev_bd = NULL;
-       } else if (journal->j_dev_bd != NULL) {
+       if (journal->j_dev_bd != NULL) {
+               if (journal->j_dev_bd->bd_dev != super->s_dev)
+                       bd_release(journal->j_dev_bd);
                result = blkdev_put(journal->j_dev_bd);
                journal->j_dev_bd = NULL;
        }
@@ -2603,7 +2601,6 @@ static int journal_init_dev(struct super_block *super,
        result = 0;
 
        journal->j_dev_bd = NULL;
-       journal->j_dev_file = NULL;
        jdev = SB_ONDISK_JOURNAL_DEVICE(super) ?
            new_decode_dev(SB_ONDISK_JOURNAL_DEVICE(super)) : super->s_dev;
 
@@ -2620,35 +2617,34 @@ static int journal_init_dev(struct super_block *super,
                                         "cannot init journal device '%s': %i",
                                         __bdevname(jdev, b), result);
                        return result;
-               } else if (jdev != super->s_dev)
+               } else if (jdev != super->s_dev) {
+                       result = bd_claim(journal->j_dev_bd, journal);
+                       if (result) {
+                               blkdev_put(journal->j_dev_bd);
+                               return result;
+                       }
+
                        set_blocksize(journal->j_dev_bd, super->s_blocksize);
+               }
+
                return 0;
        }
 
-       journal->j_dev_file = filp_open(jdev_name, 0, 0);
-       if (!IS_ERR(journal->j_dev_file)) {
-               struct inode *jdev_inode = journal->j_dev_file->f_mapping->host;
-               if (!S_ISBLK(jdev_inode->i_mode)) {
-                       reiserfs_warning(super, "journal_init_dev: '%s' is "
-                                        "not a block device", jdev_name);
-                       result = -ENOTBLK;
-                       release_journal_dev(super, journal);
-               } else {
-                       /* ok */
-                       journal->j_dev_bd = I_BDEV(jdev_inode);
-                       set_blocksize(journal->j_dev_bd, super->s_blocksize);
-                       reiserfs_info(super,
-                                     "journal_init_dev: journal device: %s\n",
-                                     bdevname(journal->j_dev_bd, b));
-               }
-       } else {
-               result = PTR_ERR(journal->j_dev_file);
-               journal->j_dev_file = NULL;
+       journal->j_dev_bd = open_bdev_excl(jdev_name, 0, journal);
+       if (IS_ERR(journal->j_dev_bd)) {
+               result = PTR_ERR(journal->j_dev_bd);
+               journal->j_dev_bd = NULL;
                reiserfs_warning(super,
                                 "journal_init_dev: Cannot open '%s': %i",
                                 jdev_name, result);
+               return result;
        }
-       return result;
+
+       set_blocksize(journal->j_dev_bd, super->s_blocksize);
+       reiserfs_info(super,
+                     "journal_init_dev: journal device: %s\n",
+                     bdevname(journal->j_dev_bd, b));
+       return 0;
 }
 
 /**
index 8f86c52b30d821884c3f576932e3e0d2e96981ba..b9dbeeca7049451e66281a1561da4f36a913703a 100644 (file)
@@ -467,6 +467,7 @@ static const struct file_operations r_file_operations = {
        .read = seq_read,
        .llseek = seq_lseek,
        .release = seq_release,
+       .owner = THIS_MODULE,
 };
 
 static struct proc_dir_entry *proc_info_root = NULL;
@@ -475,12 +476,8 @@ static const char proc_info_root_name[] = "fs/reiserfs";
 static void add_file(struct super_block *sb, char *name,
                     int (*func) (struct seq_file *, struct super_block *))
 {
-       struct proc_dir_entry *de;
-       de = create_proc_entry(name, 0, REISERFS_SB(sb)->procdir);
-       if (de) {
-               de->data = func;
-               de->proc_fops = &r_file_operations;
-       }
+       proc_create_data(name, 0, REISERFS_SB(sb)->procdir,
+                        &r_file_operations, func);
 }
 
 int reiserfs_proc_info_init(struct super_block *sb)
index 00f58c5c7e05251ef4350e762481df8b07294212..2c292146e2464836983913d7046b3279167f2ce7 100644 (file)
@@ -425,7 +425,7 @@ sticky:
        return ret;
 }
 
-#ifdef TIF_RESTORE_SIGMASK
+#ifdef HAVE_SET_RESTORE_SIGMASK
 asmlinkage long sys_pselect7(int n, fd_set __user *inp, fd_set __user *outp,
                fd_set __user *exp, struct timespec __user *tsp,
                const sigset_t __user *sigmask, size_t sigsetsize)
@@ -498,7 +498,7 @@ sticky:
                if (sigmask) {
                        memcpy(&current->saved_sigmask, &sigsaved,
                                        sizeof(sigsaved));
-                       set_thread_flag(TIF_RESTORE_SIGMASK);
+                       set_restore_sigmask();
                }
        } else if (sigmask)
                sigprocmask(SIG_SETMASK, &sigsaved, NULL);
@@ -528,7 +528,7 @@ asmlinkage long sys_pselect6(int n, fd_set __user *inp, fd_set __user *outp,
 
        return sys_pselect7(n, inp, outp, exp, tsp, up, sigsetsize);
 }
-#endif /* TIF_RESTORE_SIGMASK */
+#endif /* HAVE_SET_RESTORE_SIGMASK */
 
 struct poll_list {
        struct poll_list *next;
@@ -759,7 +759,7 @@ asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,
        return ret;
 }
 
-#ifdef TIF_RESTORE_SIGMASK
+#ifdef HAVE_SET_RESTORE_SIGMASK
 asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds,
        struct timespec __user *tsp, const sigset_t __user *sigmask,
        size_t sigsetsize)
@@ -805,7 +805,7 @@ asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds,
                if (sigmask) {
                        memcpy(&current->saved_sigmask, &sigsaved,
                                        sizeof(sigsaved));
-                       set_thread_flag(TIF_RESTORE_SIGMASK);
+                       set_restore_sigmask();
                }
                ret = -ERESTARTNOHAND;
        } else if (sigmask)
@@ -839,4 +839,4 @@ asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds,
 
        return ret;
 }
-#endif /* TIF_RESTORE_SIGMASK */
+#endif /* HAVE_SET_RESTORE_SIGMASK */
index 734972b92694f03493e9440eb86f8557ba8621f3..fc4b1a5dd75531739bdd0d856e2f85782c3fe356 100644 (file)
  * these are normally enabled.
  */
 #ifdef SMBFS_PARANOIA
-# define PARANOIA(f, a...) printk(KERN_NOTICE "%s: " f, __FUNCTION__ , ## a)
+# define PARANOIA(f, a...) printk(KERN_NOTICE "%s: " f, __func__ , ## a)
 #else
 # define PARANOIA(f, a...) do { ; } while(0)
 #endif
 
 /* lots of debug messages */
 #ifdef SMBFS_DEBUG_VERBOSE
-# define VERBOSE(f, a...) printk(KERN_DEBUG "%s: " f, __FUNCTION__ , ## a)
+# define VERBOSE(f, a...) printk(KERN_DEBUG "%s: " f, __func__ , ## a)
 #else
 # define VERBOSE(f, a...) do { ; } while(0)
 #endif
@@ -28,7 +28,7 @@
  * too common name.
  */
 #ifdef SMBFS_DEBUG
-#define DEBUG1(f, a...) printk(KERN_DEBUG "%s: " f, __FUNCTION__ , ## a)
+#define DEBUG1(f, a...) printk(KERN_DEBUG "%s: " f, __func__ , ## a)
 #else
 #define DEBUG1(f, a...) do { ; } while(0)
 #endif
index eeb1a86a701467fcc90882f803ff7b39585003fc..633f58ebfb72a2ad7b132adb7492f7c268daecca 100644 (file)
@@ -1075,7 +1075,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
 
        ret = splice_direct_to_actor(in, &sd, direct_splice_actor);
        if (ret > 0)
-               *ppos += ret;
+               *ppos = sd.pos;
 
        return ret;
 }
index a5a4aca7e22f32ed034331e000c7f9eb2bd3ae43..453877c5697be1b927bc8b9654f98f9cad71644b 100644 (file)
@@ -117,7 +117,7 @@ static inline void destroy_super(struct super_block *s)
  * Drop a superblock's refcount.  Returns non-zero if the superblock was
  * destroyed.  The caller must hold sb_lock.
  */
-int __put_super(struct super_block *sb)
+static int __put_super(struct super_block *sb)
 {
        int ret = 0;
 
index 7cd005ea76390f385dc85af2c11e8121b6b4dd69..228e17b5e9ee911c2c2f58b4090e33b96954ff23 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -64,7 +64,7 @@ int file_fsync(struct file *filp, struct dentry *dentry, int datasync)
        /* sync the superblock to buffers */
        sb = inode->i_sb;
        lock_super(sb);
-       if (sb->s_op->write_super)
+       if (sb->s_dirt && sb->s_op->write_super)
                sb->s_op->write_super(sb);
        unlock_super(sb);
 
index dbdfabbfd609661b6c585b8bc9962dae2d057634..e7735f643cd1b03eab8560479d6f691e387ce218 100644 (file)
@@ -135,7 +135,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
                        goto out;
        }
        pr_debug("%s: count = %zd, ppos = %lld, buf = %s\n",
-                __FUNCTION__, count, *ppos, buffer->page);
+                __func__, count, *ppos, buffer->page);
        retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
                                         buffer->count);
 out:
index d9262f74f94e50c3c2efacd256f9a9536dc3d850..f8b82e73b3bf0ee8a7d9403d6ffdf06ad15f5411 100644 (file)
@@ -30,7 +30,7 @@ static const struct address_space_operations sysfs_aops = {
 
 static struct backing_dev_info sysfs_backing_dev_info = {
        .ra_pages       = 0,    /* No readahead */
-       .capabilities   = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
+       .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK,
 };
 
 static const struct inode_operations sysfs_inode_operations ={
index 74168266cd59a1abca9e8039131c0ce46b240980..14f0023984d74d6a51dedc0791fdfab53f2d5cc4 100644 (file)
@@ -61,7 +61,7 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
        /* instantiate and link root dentry */
        root = d_alloc_root(inode);
        if (!root) {
-               pr_debug("%s: could not get root dentry!\n",__FUNCTION__);
+               pr_debug("%s: could not get root dentry!\n",__func__);
                iput(inode);
                return -ENOMEM;
        }
index 42d51d1c05cd418af8eeb0916fac5527ea99c258..38ebe3f85b3d092059ae81f7ad3ad6ce2db78208 100644 (file)
@@ -217,9 +217,9 @@ static inline __fs32 fs32_add(struct sysv_sb_info *sbi, __fs32 *n, int d)
        if (sbi->s_bytesex == BYTESEX_PDP)
                *(__u32*)n = PDP_swab(PDP_swab(*(__u32*)n)+d);
        else if (sbi->s_bytesex == BYTESEX_LE)
-               *(__le32*)n = cpu_to_le32(le32_to_cpu(*(__le32*)n)+d);
+               le32_add_cpu((__le32 *)n, d);
        else
-               *(__be32*)n = cpu_to_be32(be32_to_cpu(*(__be32*)n)+d);
+               be32_add_cpu((__be32 *)n, d);
        return *n;
 }
 
@@ -242,9 +242,9 @@ static inline __fs16 cpu_to_fs16(struct sysv_sb_info *sbi, __u16 n)
 static inline __fs16 fs16_add(struct sysv_sb_info *sbi, __fs16 *n, int d)
 {
        if (sbi->s_bytesex != BYTESEX_BE)
-               *(__le16*)n = cpu_to_le16(le16_to_cpu(*(__le16 *)n)+d);
+               le16_add_cpu((__le16 *)n, d);
        else
-               *(__be16*)n = cpu_to_be16(be16_to_cpu(*(__be16 *)n)+d);
+               be16_add_cpu((__be16 *)n, d);
        return *n;
 }
 
index 10c80b59ec4bb7e542b8864f369ec10da7dc34f5..5400524e9cb1d2b2e40bf810a1282277e54eec98 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/hrtimer.h>
 #include <linux/anon_inodes.h>
 #include <linux/timerfd.h>
+#include <linux/syscalls.h>
 
 struct timerfd_ctx {
        struct hrtimer tmr;
index b564fc140fe4e90efc24b7b7f231a5676aa979b6..9fb18a340fc1efa95fb0acd15d50c89c90652875 100644 (file)
@@ -240,7 +240,7 @@ static int udf_sb_alloc_partition_maps(struct super_block *sb, u32 count)
        sbi->s_partmaps = kcalloc(count, sizeof(struct udf_part_map),
                                  GFP_KERNEL);
        if (!sbi->s_partmaps) {
-               udf_error(sb, __FUNCTION__,
+               udf_error(sb, __func__,
                          "Unable to allocate space for %d partition maps",
                          count);
                sbi->s_partitions = 0;
@@ -1086,7 +1086,7 @@ static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index)
                bitmap = vmalloc(size); /* TODO: get rid of vmalloc */
 
        if (bitmap == NULL) {
-               udf_error(sb, __FUNCTION__,
+               udf_error(sb, __func__,
                          "Unable to allocate space for bitmap "
                          "and %d buffer_head pointers", nr_groups);
                return NULL;
index 5b66162d0747e647eb53f2349c19a86ed7f59cb8..a3522727ea5b090ea4ee02d925e7327cde21fe7b 100644 (file)
@@ -986,7 +986,7 @@ error_inode:
        if (corrupt < 0) {
                fat_fs_panic(new_dir->i_sb,
                             "%s: Filesystem corrupted (i_pos %lld)",
-                            __FUNCTION__, sinfo.i_pos);
+                            __func__, sinfo.i_pos);
        }
        goto out;
 }
index 89a942f07e1be839af7d8cef99e377d85db6fb27..4706a8b1f4959cdf955cc8b625ee5bac3b53ccf7 100644 (file)
@@ -67,7 +67,7 @@ xattr_permission(struct inode *inode, const char *name, int mask)
 }
 
 int
-vfs_setxattr(struct dentry *dentry, char *name, void *value,
+vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
                size_t size, int flags)
 {
        struct inode *inode = dentry->d_inode;
@@ -131,7 +131,7 @@ out_noalloc:
 EXPORT_SYMBOL_GPL(xattr_getsecurity);
 
 ssize_t
-vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
+vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
 {
        struct inode *inode = dentry->d_inode;
        int error;
@@ -187,7 +187,7 @@ vfs_listxattr(struct dentry *d, char *list, size_t size)
 EXPORT_SYMBOL_GPL(vfs_listxattr);
 
 int
-vfs_removexattr(struct dentry *dentry, char *name)
+vfs_removexattr(struct dentry *dentry, const char *name)
 {
        struct inode *inode = dentry->d_inode;
        int error;
@@ -218,7 +218,7 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
  * Extended attribute SET operations
  */
 static long
-setxattr(struct dentry *d, char __user *name, void __user *value,
+setxattr(struct dentry *d, const char __user *name, const void __user *value,
         size_t size, int flags)
 {
        int error;
@@ -252,8 +252,8 @@ setxattr(struct dentry *d, char __user *name, void __user *value,
 }
 
 asmlinkage long
-sys_setxattr(char __user *path, char __user *name, void __user *value,
-            size_t size, int flags)
+sys_setxattr(const char __user *path, const char __user *name,
+            const void __user *value, size_t size, int flags)
 {
        struct nameidata nd;
        int error;
@@ -271,8 +271,8 @@ sys_setxattr(char __user *path, char __user *name, void __user *value,
 }
 
 asmlinkage long
-sys_lsetxattr(char __user *path, char __user *name, void __user *value,
-             size_t size, int flags)
+sys_lsetxattr(const char __user *path, const char __user *name,
+             const void __user *value, size_t size, int flags)
 {
        struct nameidata nd;
        int error;
@@ -290,7 +290,7 @@ sys_lsetxattr(char __user *path, char __user *name, void __user *value,
 }
 
 asmlinkage long
-sys_fsetxattr(int fd, char __user *name, void __user *value,
+sys_fsetxattr(int fd, const char __user *name, const void __user *value,
              size_t size, int flags)
 {
        struct file *f;
@@ -315,7 +315,8 @@ sys_fsetxattr(int fd, char __user *name, void __user *value,
  * Extended attribute GET operations
  */
 static ssize_t
-getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
+getxattr(struct dentry *d, const char __user *name, void __user *value,
+        size_t size)
 {
        ssize_t error;
        void *kvalue = NULL;
@@ -349,8 +350,8 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
 }
 
 asmlinkage ssize_t
-sys_getxattr(char __user *path, char __user *name, void __user *value,
-            size_t size)
+sys_getxattr(const char __user *path, const char __user *name,
+            void __user *value, size_t size)
 {
        struct nameidata nd;
        ssize_t error;
@@ -364,7 +365,7 @@ sys_getxattr(char __user *path, char __user *name, void __user *value,
 }
 
 asmlinkage ssize_t
-sys_lgetxattr(char __user *path, char __user *name, void __user *value,
+sys_lgetxattr(const char __user *path, const char __user *name, void __user *value,
              size_t size)
 {
        struct nameidata nd;
@@ -379,7 +380,7 @@ sys_lgetxattr(char __user *path, char __user *name, void __user *value,
 }
 
 asmlinkage ssize_t
-sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size)
+sys_fgetxattr(int fd, const char __user *name, void __user *value, size_t size)
 {
        struct file *f;
        ssize_t error = -EBADF;
@@ -424,7 +425,7 @@ listxattr(struct dentry *d, char __user *list, size_t size)
 }
 
 asmlinkage ssize_t
-sys_listxattr(char __user *path, char __user *list, size_t size)
+sys_listxattr(const char __user *path, char __user *list, size_t size)
 {
        struct nameidata nd;
        ssize_t error;
@@ -438,7 +439,7 @@ sys_listxattr(char __user *path, char __user *list, size_t size)
 }
 
 asmlinkage ssize_t
-sys_llistxattr(char __user *path, char __user *list, size_t size)
+sys_llistxattr(const char __user *path, char __user *list, size_t size)
 {
        struct nameidata nd;
        ssize_t error;
@@ -470,7 +471,7 @@ sys_flistxattr(int fd, char __user *list, size_t size)
  * Extended attribute REMOVE operations
  */
 static long
-removexattr(struct dentry *d, char __user *name)
+removexattr(struct dentry *d, const char __user *name)
 {
        int error;
        char kname[XATTR_NAME_MAX + 1];
@@ -485,7 +486,7 @@ removexattr(struct dentry *d, char __user *name)
 }
 
 asmlinkage long
-sys_removexattr(char __user *path, char __user *name)
+sys_removexattr(const char __user *path, const char __user *name)
 {
        struct nameidata nd;
        int error;
@@ -503,7 +504,7 @@ sys_removexattr(char __user *path, char __user *name)
 }
 
 asmlinkage long
-sys_lremovexattr(char __user *path, char __user *name)
+sys_lremovexattr(const char __user *path, const char __user *name)
 {
        struct nameidata nd;
        int error;
@@ -521,7 +522,7 @@ sys_lremovexattr(char __user *path, char __user *name)
 }
 
 asmlinkage long
-sys_fremovexattr(int fd, char __user *name)
+sys_fremovexattr(int fd, const char __user *name)
 {
        struct file *f;
        struct dentry *dentry;
index 524021ff54367661322862d84272572171777755..3f53dd101f99340f014db68388a49351f318fb24 100644 (file)
@@ -64,3 +64,16 @@ config XFS_RT
          See the xfs man page in section 5 for additional information.
 
          If unsure, say N.
+
+config XFS_DEBUG
+       bool "XFS Debugging support (EXPERIMENTAL)"
+       depends on XFS_FS && EXPERIMENTAL
+       help
+         Say Y here to get an XFS build with many debugging features,
+         including ASSERT checks, function wrappers around macros,
+         and extra sanity-checking functions in various code paths.
+
+         Note that the resulting code will be HUGE and SLOW, and probably
+         not useful unless you are debugging a particular problem.
+
+         Say N unless you are an XFS developer, or you play one on TV.
index c110bb002665af5dce7d73d17cbb47943826d71d..ff6a19873e5cfb6a2ac45dd38514d951a45cd105 100644 (file)
 
 #include <linux/rwsem.h>
 
-enum { MR_NONE, MR_ACCESS, MR_UPDATE };
-
 typedef struct {
        struct rw_semaphore     mr_lock;
+#ifdef DEBUG
        int                     mr_writer;
+#endif
 } mrlock_t;
 
+#ifdef DEBUG
 #define mrinit(mrp, name)      \
        do { (mrp)->mr_writer = 0; init_rwsem(&(mrp)->mr_lock); } while (0)
+#else
+#define mrinit(mrp, name)      \
+       do { init_rwsem(&(mrp)->mr_lock); } while (0)
+#endif
+
 #define mrlock_init(mrp, t,n,s)        mrinit(mrp, n)
 #define mrfree(mrp)            do { } while (0)
 
-static inline void mraccess(mrlock_t *mrp)
-{
-       down_read(&mrp->mr_lock);
-}
-
-static inline void mrupdate(mrlock_t *mrp)
-{
-       down_write(&mrp->mr_lock);
-       mrp->mr_writer = 1;
-}
-
 static inline void mraccess_nested(mrlock_t *mrp, int subclass)
 {
        down_read_nested(&mrp->mr_lock, subclass);
@@ -51,10 +46,11 @@ static inline void mraccess_nested(mrlock_t *mrp, int subclass)
 static inline void mrupdate_nested(mrlock_t *mrp, int subclass)
 {
        down_write_nested(&mrp->mr_lock, subclass);
+#ifdef DEBUG
        mrp->mr_writer = 1;
+#endif
 }
 
-
 static inline int mrtryaccess(mrlock_t *mrp)
 {
        return down_read_trylock(&mrp->mr_lock);
@@ -64,39 +60,31 @@ static inline int mrtryupdate(mrlock_t *mrp)
 {
        if (!down_write_trylock(&mrp->mr_lock))
                return 0;
+#ifdef DEBUG
        mrp->mr_writer = 1;
+#endif
        return 1;
 }
 
-static inline void mrunlock(mrlock_t *mrp)
+static inline void mrunlock_excl(mrlock_t *mrp)
 {
-       if (mrp->mr_writer) {
-               mrp->mr_writer = 0;
-               up_write(&mrp->mr_lock);
-       } else {
-               up_read(&mrp->mr_lock);
-       }
+#ifdef DEBUG
+       mrp->mr_writer = 0;
+#endif
+       up_write(&mrp->mr_lock);
 }
 
-static inline void mrdemote(mrlock_t *mrp)
+static inline void mrunlock_shared(mrlock_t *mrp)
 {
-       mrp->mr_writer = 0;
-       downgrade_write(&mrp->mr_lock);
+       up_read(&mrp->mr_lock);
 }
 
-#ifdef DEBUG
-/*
- * Debug-only routine, without some platform-specific asm code, we can
- * now only answer requests regarding whether we hold the lock for write
- * (reader state is outside our visibility, we only track writer state).
- * Note: means !ismrlocked would give false positives, so don't do that.
- */
-static inline int ismrlocked(mrlock_t *mrp, int type)
+static inline void mrdemote(mrlock_t *mrp)
 {
-       if (mrp && type == MR_UPDATE)
-               return mrp->mr_writer;
-       return 1;
-}
+#ifdef DEBUG
+       mrp->mr_writer = 0;
 #endif
+       downgrade_write(&mrp->mr_lock);
+}
 
 #endif /* __XFS_SUPPORT_MRLOCK_H__ */
index 52f6846101d528b7726ba39e091c2e70dd81a6ad..5105015a75ad993d8401e0519a81186ab0e722a9 100644 (file)
@@ -886,7 +886,7 @@ int
 xfs_buf_lock_value(
        xfs_buf_t               *bp)
 {
-       return atomic_read(&bp->b_sema.count);
+       return bp->b_sema.count;
 }
 #endif
 
index 265f0168ab76ec9942a352e81421a1db23e71195..c672b3238b14b5d3a5a47b9ae606aeecd10d7fac 100644 (file)
@@ -133,7 +133,7 @@ xfs_nfs_get_inode(
        if (!ip)
                return ERR_PTR(-EIO);
 
-       if (!ip->i_d.di_mode || ip->i_d.di_gen != generation) {
+       if (ip->i_d.di_gen != generation) {
                xfs_iput_new(ip, XFS_ILOCK_SHARED);
                return ERR_PTR(-ENOENT);
        }
index 05905246434dc6e2182d2f5bbbceb2d1c480d828..65e78c13d4ae2d59a7b4eaa0785ad2c9fe95dda5 100644 (file)
@@ -43,9 +43,6 @@
 #include <linux/smp_lock.h>
 
 static struct vm_operations_struct xfs_file_vm_ops;
-#ifdef CONFIG_XFS_DMAPI
-static struct vm_operations_struct xfs_dmapi_file_vm_ops;
-#endif
 
 STATIC_INLINE ssize_t
 __xfs_file_read(
@@ -202,22 +199,6 @@ xfs_file_fsync(
                        (xfs_off_t)0, (xfs_off_t)-1);
 }
 
-#ifdef CONFIG_XFS_DMAPI
-STATIC int
-xfs_vm_fault(
-       struct vm_area_struct   *vma,
-       struct vm_fault *vmf)
-{
-       struct inode    *inode = vma->vm_file->f_path.dentry->d_inode;
-       bhv_vnode_t     *vp = vn_from_inode(inode);
-
-       ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI);
-       if (XFS_SEND_MMAP(XFS_VFSTOM(vp->v_vfsp), vma, 0))
-               return VM_FAULT_SIGBUS;
-       return filemap_fault(vma, vmf);
-}
-#endif /* CONFIG_XFS_DMAPI */
-
 /*
  * Unfortunately we can't just use the clean and simple readdir implementation
  * below, because nfs might call back into ->lookup from the filldir callback
@@ -386,11 +367,6 @@ xfs_file_mmap(
        vma->vm_ops = &xfs_file_vm_ops;
        vma->vm_flags |= VM_CAN_NONLINEAR;
 
-#ifdef CONFIG_XFS_DMAPI
-       if (XFS_M(filp->f_path.dentry->d_inode->i_sb)->m_flags & XFS_MOUNT_DMAPI)
-               vma->vm_ops = &xfs_dmapi_file_vm_ops;
-#endif /* CONFIG_XFS_DMAPI */
-
        file_accessed(filp);
        return 0;
 }
@@ -437,47 +413,6 @@ xfs_file_ioctl_invis(
        return error;
 }
 
-#ifdef CONFIG_XFS_DMAPI
-#ifdef HAVE_VMOP_MPROTECT
-STATIC int
-xfs_vm_mprotect(
-       struct vm_area_struct *vma,
-       unsigned int    newflags)
-{
-       struct inode    *inode = vma->vm_file->f_path.dentry->d_inode;
-       struct xfs_mount *mp = XFS_M(inode->i_sb);
-       int             error = 0;
-
-       if (mp->m_flags & XFS_MOUNT_DMAPI) {
-               if ((vma->vm_flags & VM_MAYSHARE) &&
-                   (newflags & VM_WRITE) && !(vma->vm_flags & VM_WRITE))
-                       error = XFS_SEND_MMAP(mp, vma, VM_WRITE);
-       }
-       return error;
-}
-#endif /* HAVE_VMOP_MPROTECT */
-#endif /* CONFIG_XFS_DMAPI */
-
-#ifdef HAVE_FOP_OPEN_EXEC
-/* If the user is attempting to execute a file that is offline then
- * we have to trigger a DMAPI READ event before the file is marked as busy
- * otherwise the invisible I/O will not be able to write to the file to bring
- * it back online.
- */
-STATIC int
-xfs_file_open_exec(
-       struct inode    *inode)
-{
-       struct xfs_mount *mp = XFS_M(inode->i_sb);
-       struct xfs_inode *ip = XFS_I(inode);
-
-       if (unlikely(mp->m_flags & XFS_MOUNT_DMAPI) &&
-                    DM_EVENT_ENABLED(ip, DM_EVENT_READ))
-               return -XFS_SEND_DATA(mp, DM_EVENT_READ, ip, 0, 0, 0, NULL);
-       return 0;
-}
-#endif /* HAVE_FOP_OPEN_EXEC */
-
 /*
  * mmap()d file has taken write protection fault and is being made
  * writable. We can set the page state up correctly for a writable
@@ -546,13 +481,3 @@ static struct vm_operations_struct xfs_file_vm_ops = {
        .fault          = filemap_fault,
        .page_mkwrite   = xfs_vm_page_mkwrite,
 };
-
-#ifdef CONFIG_XFS_DMAPI
-static struct vm_operations_struct xfs_dmapi_file_vm_ops = {
-       .fault          = xfs_vm_fault,
-       .page_mkwrite   = xfs_vm_page_mkwrite,
-#ifdef HAVE_VMOP_MPROTECT
-       .mprotect       = xfs_vm_mprotect,
-#endif
-};
-#endif /* CONFIG_XFS_DMAPI */
index 4ddb86b73c6b537034b09d2632c7d2061432a736..a42ba9d71156f84101e1068a33d4bd05e055bcd9 100644 (file)
@@ -238,7 +238,7 @@ xfs_vget_fsop_handlereq(
                return error;
        if (ip == NULL)
                return XFS_ERROR(EIO);
-       if (ip->i_d.di_mode == 0 || ip->i_d.di_gen != igen) {
+       if (ip->i_d.di_gen != igen) {
                xfs_iput_new(ip, XFS_ILOCK_SHARED);
                return XFS_ERROR(ENOENT);
        }
@@ -505,14 +505,14 @@ xfs_attrmulti_attr_get(
 {
        char                    *kbuf;
        int                     error = EFAULT;
-       
+
        if (*len > XATTR_SIZE_MAX)
                return EINVAL;
        kbuf = kmalloc(*len, GFP_KERNEL);
        if (!kbuf)
                return ENOMEM;
 
-       error = xfs_attr_get(XFS_I(inode), name, kbuf, (int *)len, flags, NULL);
+       error = xfs_attr_get(XFS_I(inode), name, kbuf, (int *)len, flags);
        if (error)
                goto out_kfree;
 
@@ -546,7 +546,7 @@ xfs_attrmulti_attr_set(
 
        if (copy_from_user(kbuf, ubuf, len))
                goto out_kfree;
-                       
+
        error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags);
 
  out_kfree:
index a1237dad6430b28221be1dc033f6f0a4e599f2cf..2bf287ef54897af2651f24b39792404270179a19 100644 (file)
@@ -511,7 +511,8 @@ xfs_vn_rename(
        xfs_dentry_to_name(&nname, ndentry);
 
        error = xfs_rename(XFS_I(odir), &oname, XFS_I(odentry->d_inode),
-                                                       XFS_I(ndir), &nname);
+                          XFS_I(ndir), &nname, new_inode ?
+                                               XFS_I(new_inode) : NULL);
        if (likely(!error)) {
                if (new_inode)
                        xfs_validate_fields(new_inode);
index e5143323e71f35ba82167013843539e19b34c15e..4edc46915b575a7eb1261f2bda587cfbccfe0462 100644 (file)
@@ -75,6 +75,7 @@
 #include <linux/delay.h>
 #include <linux/log2.h>
 #include <linux/spinlock.h>
+#include <linux/random.h>
 
 #include <asm/page.h>
 #include <asm/div64.h>
 /*
  * Feature macros (disable/enable)
  */
-#define HAVE_SPLICE    /* a splice(2) exists in 2.6, but not in 2.4 */
 #ifdef CONFIG_SMP
 #define HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */
 #else
index 1ebd8004469c1d3a70a0afc0f8a34f8400ea5011..5e3b57516ec7293fe8bffe42cc995b9025780b8e 100644 (file)
@@ -394,7 +394,7 @@ xfs_zero_last_block(
        int             error = 0;
        xfs_bmbt_irec_t imap;
 
-       ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0);
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 
        zero_offset = XFS_B_FSB_OFFSET(mp, isize);
        if (zero_offset == 0) {
@@ -425,14 +425,14 @@ xfs_zero_last_block(
         * out sync.  We need to drop the ilock while we do this so we
         * don't deadlock when the buffer cache calls back to us.
         */
-       xfs_iunlock(ip, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD);
+       xfs_iunlock(ip, XFS_ILOCK_EXCL);
 
        zero_len = mp->m_sb.sb_blocksize - zero_offset;
        if (isize + zero_len > offset)
                zero_len = offset - isize;
        error = xfs_iozero(ip, isize, zero_len);
 
-       xfs_ilock(ip, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
+       xfs_ilock(ip, XFS_ILOCK_EXCL);
        ASSERT(error >= 0);
        return error;
 }
@@ -465,8 +465,7 @@ xfs_zero_eof(
        int             error = 0;
        xfs_bmbt_irec_t imap;
 
-       ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
-       ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
        ASSERT(offset > isize);
 
        /*
@@ -475,8 +474,7 @@ xfs_zero_eof(
         */
        error = xfs_zero_last_block(ip, offset, isize);
        if (error) {
-               ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
-               ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE));
+               ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
                return error;
        }
 
@@ -507,8 +505,7 @@ xfs_zero_eof(
                error = xfs_bmapi(NULL, ip, start_zero_fsb, zero_count_fsb,
                                  0, NULL, 0, &imap, &nimaps, NULL, NULL);
                if (error) {
-                       ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
-                       ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE));
+                       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
                        return error;
                }
                ASSERT(nimaps > 0);
@@ -532,7 +529,7 @@ xfs_zero_eof(
                 * Drop the inode lock while we're doing the I/O.
                 * We'll still have the iolock to protect us.
                 */
-               xfs_iunlock(ip, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
+               xfs_iunlock(ip, XFS_ILOCK_EXCL);
 
                zero_off = XFS_FSB_TO_B(mp, start_zero_fsb);
                zero_len = XFS_FSB_TO_B(mp, imap.br_blockcount);
@@ -548,13 +545,13 @@ xfs_zero_eof(
                start_zero_fsb = imap.br_startoff + imap.br_blockcount;
                ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
 
-               xfs_ilock(ip, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
+               xfs_ilock(ip, XFS_ILOCK_EXCL);
        }
 
        return 0;
 
 out_lock:
-       xfs_ilock(ip, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
+       xfs_ilock(ip, XFS_ILOCK_EXCL);
        ASSERT(error >= 0);
        return error;
 }
index e1d498b4ba7a98e1a9bf0049c165d6331290b7a3..e6be37dbd0e9f8865e81e5b442758d2c7d24dcaa 100644 (file)
@@ -50,7 +50,6 @@ struct xfs_iomap;
 #define        XFS_INVAL_CACHED        18
 #define        XFS_DIORD_ENTER         19
 #define        XFS_DIOWR_ENTER         20
-#define        XFS_SENDFILE_ENTER      21
 #define        XFS_WRITEPAGE_ENTER     22
 #define        XFS_RELEASEPAGE_ENTER   23
 #define        XFS_INVALIDPAGE_ENTER   24
index 865eb708aa95ffdca5c528b2a9871c2b78aaacdb..742b2c7852c1bc947ae93e3a11dd499cecab8fdb 100644 (file)
@@ -1181,7 +1181,7 @@ xfs_fs_statfs(
        statp->f_fsid.val[0] = (u32)id;
        statp->f_fsid.val[1] = (u32)(id >> 32);
 
-       xfs_icsb_sync_counters_flags(mp, XFS_ICSB_LAZY_COUNT);
+       xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
 
        spin_lock(&mp->m_sb_lock);
        statp->f_bsize = sbp->sb_blocksize;
index 8b4d63ce86945cf00edf197c38b02cbb9d36bb09..9d73cb5c0fc7f664fee65bc2344c41d31535193b 100644 (file)
@@ -25,12 +25,6 @@ struct attrlist_cursor_kern;
 
 typedef struct inode   bhv_vnode_t;
 
-#define VN_ISLNK(vp)   S_ISLNK((vp)->i_mode)
-#define VN_ISREG(vp)   S_ISREG((vp)->i_mode)
-#define VN_ISDIR(vp)   S_ISDIR((vp)->i_mode)
-#define VN_ISCHR(vp)   S_ISCHR((vp)->i_mode)
-#define VN_ISBLK(vp)   S_ISBLK((vp)->i_mode)
-
 /*
  * Vnode to Linux inode mapping.
  */
@@ -151,24 +145,6 @@ typedef struct bhv_vattr {
                XFS_AT_TYPE|XFS_AT_BLKSIZE|XFS_AT_NBLOCKS|XFS_AT_VCODE|\
                XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|XFS_AT_GENCOUNT)
 
-/*
- *  Modes.
- */
-#define VSUID  S_ISUID         /* set user id on execution */
-#define VSGID  S_ISGID         /* set group id on execution */
-#define VSVTX  S_ISVTX         /* save swapped text even after use */
-#define VREAD  S_IRUSR         /* read, write, execute permissions */
-#define VWRITE S_IWUSR
-#define VEXEC  S_IXUSR
-
-#define MODEMASK S_IALLUGO     /* mode bits plus permission bits */
-
-/*
- * Check whether mandatory file locking is enabled.
- */
-#define MANDLOCK(vp, mode)     \
-       (VN_ISREG(vp) && ((mode) & (VSGID|(VEXEC>>3))) == VSGID)
-
 extern void    vn_init(void);
 extern int     vn_revalidate(bhv_vnode_t *);
 
index 631ebb31b295df30fed95207e80be2214d5f2f49..85df3288efd5b8530ad2ff42b23f10ce9104cb25 100644 (file)
@@ -933,7 +933,7 @@ xfs_qm_dqget(
               type == XFS_DQ_PROJ ||
               type == XFS_DQ_GROUP);
        if (ip) {
-               ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
+               ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
                if (type == XFS_DQ_USER)
                        ASSERT(ip->i_udquot == NULL);
                else
@@ -1088,7 +1088,7 @@ xfs_qm_dqget(
        xfs_qm_mplist_unlock(mp);
        XFS_DQ_HASH_UNLOCK(h);
  dqret:
-       ASSERT((ip == NULL) || XFS_ISLOCKED_INODE_EXCL(ip));
+       ASSERT((ip == NULL) || xfs_isilocked(ip, XFS_ILOCK_EXCL));
        xfs_dqtrace_entry(dqp, "DQGET DONE");
        *O_dqpp = dqp;
        return (0);
index 40ea56409561cd8b98a180f6c1cd639c8f30476e..d31cce1165c59cd03ad1c8590c5bbc487494b95a 100644 (file)
@@ -670,7 +670,7 @@ xfs_qm_dqattach_one(
        xfs_dquot_t     *dqp;
        int             error;
 
-       ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        error = 0;
        /*
         * See if we already have it in the inode itself. IO_idqpp is
@@ -874,7 +874,7 @@ xfs_qm_dqattach(
                return 0;
 
        ASSERT((flags & XFS_QMOPT_ILOCKED) == 0 ||
-              XFS_ISLOCKED_INODE_EXCL(ip));
+              xfs_isilocked(ip, XFS_ILOCK_EXCL));
 
        if (! (flags & XFS_QMOPT_ILOCKED))
                xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -888,7 +888,8 @@ xfs_qm_dqattach(
                        goto done;
                nquotas++;
        }
-       ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
+
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        if (XFS_IS_OQUOTA_ON(mp)) {
                error = XFS_IS_GQUOTA_ON(mp) ?
                        xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
@@ -913,7 +914,7 @@ xfs_qm_dqattach(
         * This WON'T, in general, result in a thrash.
         */
        if (nquotas == 2) {
-               ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
+               ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
                ASSERT(ip->i_udquot);
                ASSERT(ip->i_gdquot);
 
@@ -956,7 +957,7 @@ xfs_qm_dqattach(
 
 #ifdef QUOTADEBUG
        else
-               ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
+               ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 #endif
        return error;
 }
@@ -1291,7 +1292,7 @@ xfs_qm_dqget_noattach(
        xfs_mount_t     *mp;
        xfs_dquot_t     *udqp, *gdqp;
 
-       ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        mp = ip->i_mount;
        udqp = NULL;
        gdqp = NULL;
@@ -1392,7 +1393,7 @@ xfs_qm_qino_alloc(
         * Keep an extra reference to this quota inode. This inode is
         * locked exclusively and joined to the transaction already.
         */
-       ASSERT(XFS_ISLOCKED_INODE_EXCL(*ip));
+       ASSERT(xfs_isilocked(*ip, XFS_ILOCK_EXCL));
        VN_HOLD(XFS_ITOV((*ip)));
 
        /*
@@ -1737,12 +1738,6 @@ xfs_qm_dqusage_adjust(
                return error;
        }
 
-       if (ip->i_d.di_mode == 0) {
-               xfs_iput_new(ip, XFS_ILOCK_EXCL);
-               *res = BULKSTAT_RV_NOTHING;
-               return XFS_ERROR(ENOENT);
-       }
-
        /*
         * Obtain the locked dquots. In case of an error (eg. allocation
         * fails for ENOSPC), we return the negative of the error number
@@ -2563,7 +2558,7 @@ xfs_qm_vop_chown(
        uint            bfield = XFS_IS_REALTIME_INODE(ip) ?
                                 XFS_TRANS_DQ_RTBCOUNT : XFS_TRANS_DQ_BCOUNT;
 
-       ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
 
        /* old dquot */
@@ -2607,7 +2602,7 @@ xfs_qm_vop_chown_reserve(
        uint            delblks, blkflags, prjflags = 0;
        xfs_dquot_t     *unresudq, *unresgdq, *delblksudq, *delblksgdq;
 
-       ASSERT(XFS_ISLOCKED_INODE(ip));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
        mp = ip->i_mount;
        ASSERT(XFS_IS_QUOTA_RUNNING(mp));
 
@@ -2717,7 +2712,7 @@ xfs_qm_vop_dqattach_and_dqmod_newinode(
        if (!XFS_IS_QUOTA_ON(tp->t_mountp))
                return;
 
-       ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        ASSERT(XFS_IS_QUOTA_RUNNING(tp->t_mountp));
 
        if (udqp) {
index 8342823dbdc34913548e9bd285de1bb8aa991f7c..768a3b27d2b67c68a5361c853b277e778c8f0c8e 100644 (file)
@@ -1366,12 +1366,6 @@ xfs_qm_internalqcheck_adjust(
                return (error);
        }
 
-       if (ip->i_d.di_mode == 0) {
-               xfs_iput_new(ip, lock_flags);
-               *res = BULKSTAT_RV_NOTHING;
-               return XFS_ERROR(ENOENT);
-       }
-
        /*
         * This inode can have blocks after eof which can get released
         * when we send it to inactive. Since we don't check the dquot
index a8b85e2be9d5cf34d10ecaa332d4b9257a82efd1..5e4a40b1c565c3d9388669145b768496a3e345fd 100644 (file)
 /* Number of dquots that fit in to a dquot block */
 #define XFS_QM_DQPERBLK(mp)    ((mp)->m_quotainfo->qi_dqperchunk)
 
-#define XFS_ISLOCKED_INODE(ip)         (ismrlocked(&(ip)->i_lock, \
-                                           MR_UPDATE | MR_ACCESS) != 0)
-#define XFS_ISLOCKED_INODE_EXCL(ip)    (ismrlocked(&(ip)->i_lock, \
-                                           MR_UPDATE) != 0)
-
 #define XFS_DQ_IS_ADDEDTO_TRX(t, d)    ((d)->q_transp == (t))
 
 #define XFS_QI_MPLRECLAIMS(mp) ((mp)->m_quotainfo->qi_dqreclaims)
index f441f836ca8b29338cbc5c1e5b8a7e4b9fad8677..99611381e74043f9974651d2179c08cbc83f9675 100644 (file)
@@ -834,7 +834,7 @@ xfs_trans_reserve_quota_nblks(
        ASSERT(ip->i_ino != mp->m_sb.sb_uquotino);
        ASSERT(ip->i_ino != mp->m_sb.sb_gquotino);
 
-       ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
        ASSERT((flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==
                                XFS_TRANS_DQ_RES_RTBLKS ||
index 855da04086479481a60c5d5a9dd271fb37c57bc7..75845f950814ca8beac0bf2941eea886d8446271 100644 (file)
@@ -49,8 +49,6 @@ extern void assfail(char *expr, char *f, int l);
 
 #else /* DEBUG */
 
-#include <linux/random.h>
-
 #define ASSERT(expr)   \
        (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
 
index 765aaf65e2d3e984c8d872925ab16fab66d1ed56..540e4c98982512a365eeccc4bd7f5d16b1d9db63 100644 (file)
@@ -22,7 +22,7 @@
 #define STATIC
 #define DEBUG 1
 #define XFS_BUF_LOCK_TRACKING 1
-#define QUOTADEBUG 1
+/* #define QUOTADEBUG 1 */
 #endif
 
 #ifdef CONFIG_XFS_TRACE
index 8e130b9720ae8513d24a2307c5aba0a034718dac..ebee3a4f703aa5128756e950631a3bd3f50e7103 100644 (file)
@@ -72,7 +72,7 @@ xfs_acl_vhasacl_default(
 {
        int             error;
 
-       if (!VN_ISDIR(vp))
+       if (!S_ISDIR(vp->i_mode))
                return 0;
        xfs_acl_get_attr(vp, NULL, _ACL_TYPE_DEFAULT, ATTR_KERNOVAL, &error);
        return (error == 0);
@@ -238,15 +238,8 @@ xfs_acl_vget(
                        error = EINVAL;
                        goto out;
                }
-               if (kind == _ACL_TYPE_ACCESS) {
-                       bhv_vattr_t     va;
-
-                       va.va_mask = XFS_AT_MODE;
-                       error = xfs_getattr(xfs_vtoi(vp), &va, 0);
-                       if (error)
-                               goto out;
-                       xfs_acl_sync_mode(va.va_mode, xfs_acl);
-               }
+               if (kind == _ACL_TYPE_ACCESS)
+                       xfs_acl_sync_mode(xfs_vtoi(vp)->i_d.di_mode, xfs_acl);
                error = -posix_acl_xfs_to_xattr(xfs_acl, ext_acl, size);
        }
 out:
@@ -341,14 +334,15 @@ xfs_acl_iaccess(
 {
        xfs_acl_t       *acl;
        int             rval;
+       struct xfs_name acl_name = {SGI_ACL_FILE, SGI_ACL_FILE_SIZE};
 
        if (!(_ACL_ALLOC(acl)))
                return -1;
 
        /* If the file has no ACL return -1. */
        rval = sizeof(xfs_acl_t);
-       if (xfs_attr_fetch(ip, SGI_ACL_FILE, SGI_ACL_FILE_SIZE,
-                       (char *)acl, &rval, ATTR_ROOT | ATTR_KERNACCESS, cr)) {
+       if (xfs_attr_fetch(ip, &acl_name, (char *)acl, &rval,
+                                       ATTR_ROOT | ATTR_KERNACCESS)) {
                _ACL_FREE(acl);
                return -1;
        }
@@ -373,23 +367,15 @@ xfs_acl_allow_set(
        bhv_vnode_t     *vp,
        int             kind)
 {
-       xfs_inode_t     *ip = xfs_vtoi(vp);
-       bhv_vattr_t     va;
-       int             error;
-
        if (vp->i_flags & (S_IMMUTABLE|S_APPEND))
                return EPERM;
-       if (kind == _ACL_TYPE_DEFAULT && !VN_ISDIR(vp))
+       if (kind == _ACL_TYPE_DEFAULT && !S_ISDIR(vp->i_mode))
                return ENOTDIR;
        if (vp->i_sb->s_flags & MS_RDONLY)
                return EROFS;
-       va.va_mask = XFS_AT_UID;
-       error = xfs_getattr(ip, &va, 0);
-       if (error)
-               return error;
-       if (va.va_uid != current->fsuid && !capable(CAP_FOWNER))
+       if (xfs_vtoi(vp)->i_d.di_uid != current->fsuid && !capable(CAP_FOWNER))
                return EPERM;
-       return error;
+       return 0;
 }
 
 /*
@@ -594,7 +580,7 @@ xfs_acl_get_attr(
        *error = xfs_attr_get(xfs_vtoi(vp),
                                        kind == _ACL_TYPE_ACCESS ?
                                        SGI_ACL_FILE : SGI_ACL_DEFAULT,
-                                       (char *)aclp, &len, flags, sys_cred);
+                                       (char *)aclp, &len, flags);
        if (*error || (flags & ATTR_KERNOVAL))
                return;
        xfs_acl_get_endian(aclp);
@@ -643,7 +629,6 @@ xfs_acl_vtoacl(
        xfs_acl_t       *access_acl,
        xfs_acl_t       *default_acl)
 {
-       bhv_vattr_t     va;
        int             error = 0;
 
        if (access_acl) {
@@ -652,16 +637,10 @@ xfs_acl_vtoacl(
                 * be obtained for some reason, invalidate the access ACL.
                 */
                xfs_acl_get_attr(vp, access_acl, _ACL_TYPE_ACCESS, 0, &error);
-               if (!error) {
-                       /* Got the ACL, need the mode... */
-                       va.va_mask = XFS_AT_MODE;
-                       error = xfs_getattr(xfs_vtoi(vp), &va, 0);
-               }
-
                if (error)
                        access_acl->acl_cnt = XFS_ACL_NOT_PRESENT;
                else /* We have a good ACL and the file mode, synchronize. */
-                       xfs_acl_sync_mode(va.va_mode, access_acl);
+                       xfs_acl_sync_mode(xfs_vtoi(vp)->i_d.di_mode, access_acl);
        }
 
        if (default_acl) {
@@ -719,7 +698,7 @@ xfs_acl_inherit(
         * If the new file is a directory, its default ACL is a copy of
         * the containing directory's default ACL.
         */
-       if (VN_ISDIR(vp))
+       if (S_ISDIR(vp->i_mode))
                xfs_acl_set_attr(vp, pdaclp, _ACL_TYPE_DEFAULT, &error);
        if (!error && !basicperms)
                xfs_acl_set_attr(vp, cacl, _ACL_TYPE_ACCESS, &error);
@@ -744,7 +723,7 @@ xfs_acl_setmode(
        bhv_vattr_t     va;
        xfs_acl_entry_t *ap;
        xfs_acl_entry_t *gap = NULL;
-       int             i, error, nomask = 1;
+       int             i, nomask = 1;
 
        *basicperms = 1;
 
@@ -756,11 +735,7 @@ xfs_acl_setmode(
         * mode.  The m:: bits take precedence over the g:: bits.
         */
        va.va_mask = XFS_AT_MODE;
-       error = xfs_getattr(xfs_vtoi(vp), &va, 0);
-       if (error)
-               return error;
-
-       va.va_mask = XFS_AT_MODE;
+       va.va_mode = xfs_vtoi(vp)->i_d.di_mode;
        va.va_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO);
        ap = acl->acl_entry;
        for (i = 0; i < acl->acl_cnt; ++i) {
index 36d781ee5fcc6ab6b884bce5b419610bfa7a4843..df151a859186cdf569ae2e3436af8157e0812887 100644 (file)
@@ -101,14 +101,28 @@ STATIC int xfs_attr_rmtval_remove(xfs_da_args_t *args);
 ktrace_t *xfs_attr_trace_buf;
 #endif
 
+STATIC int
+xfs_attr_name_to_xname(
+       struct xfs_name *xname,
+       const char      *aname)
+{
+       if (!aname)
+               return EINVAL;
+       xname->name = aname;
+       xname->len = strlen(aname);
+       if (xname->len >= MAXNAMELEN)
+               return EFAULT;          /* match IRIX behaviour */
+
+       return 0;
+}
 
 /*========================================================================
  * Overall external interface routines.
  *========================================================================*/
 
 int
-xfs_attr_fetch(xfs_inode_t *ip, const char *name, int namelen,
-              char *value, int *valuelenp, int flags, struct cred *cred)
+xfs_attr_fetch(xfs_inode_t *ip, struct xfs_name *name,
+               char *value, int *valuelenp, int flags)
 {
        xfs_da_args_t   args;
        int             error;
@@ -122,8 +136,8 @@ xfs_attr_fetch(xfs_inode_t *ip, const char *name, int namelen,
         * Fill in the arg structure for this request.
         */
        memset((char *)&args, 0, sizeof(args));
-       args.name = name;
-       args.namelen = namelen;
+       args.name = name->name;
+       args.namelen = name->len;
        args.value = value;
        args.valuelen = *valuelenp;
        args.flags = flags;
@@ -162,31 +176,29 @@ xfs_attr_get(
        const char      *name,
        char            *value,
        int             *valuelenp,
-       int             flags,
-       cred_t          *cred)
+       int             flags)
 {
-       int             error, namelen;
+       int             error;
+       struct xfs_name xname;
 
        XFS_STATS_INC(xs_attr_get);
 
-       if (!name)
-               return(EINVAL);
-       namelen = strlen(name);
-       if (namelen >= MAXNAMELEN)
-               return(EFAULT);         /* match IRIX behaviour */
-
        if (XFS_FORCED_SHUTDOWN(ip->i_mount))
                return(EIO);
 
+       error = xfs_attr_name_to_xname(&xname, name);
+       if (error)
+               return error;
+
        xfs_ilock(ip, XFS_ILOCK_SHARED);
-       error = xfs_attr_fetch(ip, name, namelen, value, valuelenp, flags, cred);
+       error = xfs_attr_fetch(ip, &xname, value, valuelenp, flags);
        xfs_iunlock(ip, XFS_ILOCK_SHARED);
        return(error);
 }
 
-int
-xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
-                char *value, int valuelen, int flags)
+STATIC int
+xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name,
+               char *value, int valuelen, int flags)
 {
        xfs_da_args_t   args;
        xfs_fsblock_t   firstblock;
@@ -209,7 +221,7 @@ xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
         */
        if (XFS_IFORK_Q(dp) == 0) {
                int sf_size = sizeof(xfs_attr_sf_hdr_t) +
-                             XFS_ATTR_SF_ENTSIZE_BYNAME(namelen, valuelen);
+                             XFS_ATTR_SF_ENTSIZE_BYNAME(name->len, valuelen);
 
                if ((error = xfs_bmap_add_attrfork(dp, sf_size, rsvd)))
                        return(error);
@@ -219,8 +231,8 @@ xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
         * Fill in the arg structure for this request.
         */
        memset((char *)&args, 0, sizeof(args));
-       args.name = name;
-       args.namelen = namelen;
+       args.name = name->name;
+       args.namelen = name->len;
        args.value = value;
        args.valuelen = valuelen;
        args.flags = flags;
@@ -236,7 +248,7 @@ xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
         * Determine space new attribute will use, and if it would be
         * "local" or "remote" (note: local != inline).
         */
-       size = xfs_attr_leaf_newentsize(namelen, valuelen,
+       size = xfs_attr_leaf_newentsize(name->len, valuelen,
                                        mp->m_sb.sb_blocksize, &local);
 
        nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
@@ -429,26 +441,27 @@ xfs_attr_set(
        int             valuelen,
        int             flags)
 {
-       int             namelen;
-
-       namelen = strlen(name);
-       if (namelen >= MAXNAMELEN)
-               return EFAULT;          /* match IRIX behaviour */
+       int             error;
+       struct xfs_name xname;
 
        XFS_STATS_INC(xs_attr_set);
 
        if (XFS_FORCED_SHUTDOWN(dp->i_mount))
                return (EIO);
 
-       return xfs_attr_set_int(dp, name, namelen, value, valuelen, flags);
+       error = xfs_attr_name_to_xname(&xname, name);
+       if (error)
+               return error;
+
+       return xfs_attr_set_int(dp, &xname, value, valuelen, flags);
 }
 
 /*
  * Generic handler routine to remove a name from an attribute list.
  * Transitions attribute list from Btree to shortform as necessary.
  */
-int
-xfs_attr_remove_int(xfs_inode_t *dp, const char *name, int namelen, int flags)
+STATIC int
+xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
 {
        xfs_da_args_t   args;
        xfs_fsblock_t   firstblock;
@@ -460,8 +473,8 @@ xfs_attr_remove_int(xfs_inode_t *dp, const char *name, int namelen, int flags)
         * Fill in the arg structure for this request.
         */
        memset((char *)&args, 0, sizeof(args));
-       args.name = name;
-       args.namelen = namelen;
+       args.name = name->name;
+       args.namelen = name->len;
        args.flags = flags;
        args.hashval = xfs_da_hashname(args.name, args.namelen);
        args.dp = dp;
@@ -575,17 +588,18 @@ xfs_attr_remove(
        const char      *name,
        int             flags)
 {
-       int             namelen;
-
-       namelen = strlen(name);
-       if (namelen >= MAXNAMELEN)
-               return EFAULT;          /* match IRIX behaviour */
+       int             error;
+       struct xfs_name xname;
 
        XFS_STATS_INC(xs_attr_remove);
 
        if (XFS_FORCED_SHUTDOWN(dp->i_mount))
                return (EIO);
 
+       error = xfs_attr_name_to_xname(&xname, name);
+       if (error)
+               return error;
+
        xfs_ilock(dp, XFS_ILOCK_SHARED);
        if (XFS_IFORK_Q(dp) == 0 ||
                   (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
@@ -595,10 +609,10 @@ xfs_attr_remove(
        }
        xfs_iunlock(dp, XFS_ILOCK_SHARED);
 
-       return xfs_attr_remove_int(dp, name, namelen, flags);
+       return xfs_attr_remove_int(dp, &xname, flags);
 }
 
-int                                                            /* error */
+STATIC int
 xfs_attr_list_int(xfs_attr_list_context_t *context)
 {
        int error;
@@ -2522,8 +2536,7 @@ attr_generic_get(
 {
        int     error, asize = size;
 
-       error = xfs_attr_get(xfs_vtoi(vp), name, data,
-                                   &asize, xflags, NULL);
+       error = xfs_attr_get(xfs_vtoi(vp), name, data, &asize, xflags);
        if (!error)
                return asize;
        return -error;
index 786eba3121c4300a0b2a349167c7f29b2a1121e8..6cfc9384fe35c952640edc8baa04ca6d4c1d3b78 100644 (file)
@@ -158,14 +158,10 @@ struct xfs_da_args;
 /*
  * Overall external interface routines.
  */
-int xfs_attr_set_int(struct xfs_inode *, const char *, int, char *, int, int);
-int xfs_attr_remove_int(struct xfs_inode *, const char *, int, int);
-int xfs_attr_list_int(struct xfs_attr_list_context *);
 int xfs_attr_inactive(struct xfs_inode *dp);
 
 int xfs_attr_shortform_getvalue(struct xfs_da_args *);
-int xfs_attr_fetch(struct xfs_inode *, const char *, int,
-                       char *, int *, int, struct cred *);
+int xfs_attr_fetch(struct xfs_inode *, struct xfs_name *, char *, int *, int);
 int xfs_attr_rmtval_get(struct xfs_da_args *args);
 
 #endif /* __XFS_ATTR_H__ */
index eb198c01c35dd08d306c0a53da2109bedc015afa..53c259f5a5af5e7b85fde5f73ee678670e692ad9 100644 (file)
@@ -4074,7 +4074,6 @@ xfs_bmap_add_attrfork(
 error2:
        xfs_bmap_cancel(&flist);
 error1:
-       ASSERT(ismrlocked(&ip->i_lock,MR_UPDATE));
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
 error0:
        xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
index 3f53fad356a30a199e11ad761d47cb6b53aa6252..5f3647cb98851aa13855ed53d26d102bdb0f08c7 100644 (file)
@@ -162,7 +162,7 @@ xfs_swap_extents(
                ips[1] = ip;
        }
 
-       xfs_lock_inodes(ips, 2, 0, lock_flags);
+       xfs_lock_inodes(ips, 2, lock_flags);
        locked = 1;
 
        /* Verify that both files have the same format */
@@ -265,7 +265,7 @@ xfs_swap_extents(
                locked = 0;
                goto error0;
        }
-       xfs_lock_inodes(ips, 2, 0, XFS_ILOCK_EXCL);
+       xfs_lock_inodes(ips, 2, XFS_ILOCK_EXCL);
 
        /*
         * Count the number of extended attribute blocks
index d3a0f538d6a67a8bdb7ebdc21f33a02f569a5a6e..381ebda4f7bc606c484d504e665769ab45a08377 100644 (file)
@@ -462,7 +462,7 @@ xfs_fs_counts(
        xfs_mount_t             *mp,
        xfs_fsop_counts_t       *cnt)
 {
-       xfs_icsb_sync_counters_flags(mp, XFS_ICSB_LAZY_COUNT);
+       xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT);
        spin_lock(&mp->m_sb_lock);
        cnt->freedata = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
        cnt->freertx = mp->m_sb.sb_frextents;
@@ -524,7 +524,7 @@ xfs_reserve_blocks(
         */
 retry:
        spin_lock(&mp->m_sb_lock);
-       xfs_icsb_sync_counters_flags(mp, XFS_ICSB_SB_LOCKED);
+       xfs_icsb_sync_counters_locked(mp, 0);
 
        /*
         * If our previous reservation was larger than the current value,
@@ -552,11 +552,8 @@ retry:
                        mp->m_resblks += free;
                        mp->m_resblks_avail += free;
                        fdblks_delta = -free;
-                       mp->m_sb.sb_fdblocks = XFS_ALLOC_SET_ASIDE(mp);
                } else {
                        fdblks_delta = -delta;
-                       mp->m_sb.sb_fdblocks =
-                               lcounter + XFS_ALLOC_SET_ASIDE(mp);
                        mp->m_resblks = request;
                        mp->m_resblks_avail += delta;
                }
@@ -587,7 +584,6 @@ out:
                if (error == ENOSPC)
                        goto retry;
        }
-
        return 0;
 }
 
index a64dfbd565a563b3886d934ec19d77df4f4ed526..aad8c5da38afadb158518d7ee5dc51a3309726f2 100644 (file)
@@ -147,6 +147,7 @@ xfs_ialloc_ag_alloc(
        int             version;        /* inode version number to use */
        int             isaligned = 0;  /* inode allocation at stripe unit */
                                        /* boundary */
+       unsigned int    gen;
 
        args.tp = tp;
        args.mp = tp->t_mountp;
@@ -290,6 +291,14 @@ xfs_ialloc_ag_alloc(
        else
                version = XFS_DINODE_VERSION_1;
 
+       /*
+        * Seed the new inode cluster with a random generation number. This
+        * prevents short-term reuse of generation numbers if a chunk is
+        * freed and then immediately reallocated. We use random numbers
+        * rather than a linear progression to prevent the next generation
+        * number from being easily guessable.
+        */
+       gen = random32();
        for (j = 0; j < nbufs; j++) {
                /*
                 * Get the block.
@@ -309,6 +318,7 @@ xfs_ialloc_ag_alloc(
                        free = XFS_MAKE_IPTR(args.mp, fbuf, i);
                        free->di_core.di_magic = cpu_to_be16(XFS_DINODE_MAGIC);
                        free->di_core.di_version = version;
+                       free->di_core.di_gen = cpu_to_be32(gen);
                        free->di_next_unlinked = cpu_to_be32(NULLAGINO);
                        xfs_ialloc_log_di(tp, fbuf, i,
                                XFS_DI_CORE_BITS | XFS_DI_NEXT_UNLINKED);
index e657c51284606c8d3e98f9a18dee5a7294834be2..b07604b94d9f32c2f15e7eb08c5e83b458b3fd42 100644 (file)
@@ -593,8 +593,9 @@ xfs_iunlock_map_shared(
  *             XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL
  */
 void
-xfs_ilock(xfs_inode_t  *ip,
-         uint          lock_flags)
+xfs_ilock(
+       xfs_inode_t             *ip,
+       uint                    lock_flags)
 {
        /*
         * You can't set both SHARED and EXCL for the same lock,
@@ -607,16 +608,16 @@ xfs_ilock(xfs_inode_t     *ip,
               (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
        ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
 
-       if (lock_flags & XFS_IOLOCK_EXCL) {
+       if (lock_flags & XFS_IOLOCK_EXCL)
                mrupdate_nested(&ip->i_iolock, XFS_IOLOCK_DEP(lock_flags));
-       } else if (lock_flags & XFS_IOLOCK_SHARED) {
+       else if (lock_flags & XFS_IOLOCK_SHARED)
                mraccess_nested(&ip->i_iolock, XFS_IOLOCK_DEP(lock_flags));
-       }
-       if (lock_flags & XFS_ILOCK_EXCL) {
+
+       if (lock_flags & XFS_ILOCK_EXCL)
                mrupdate_nested(&ip->i_lock, XFS_ILOCK_DEP(lock_flags));
-       } else if (lock_flags & XFS_ILOCK_SHARED) {
+       else if (lock_flags & XFS_ILOCK_SHARED)
                mraccess_nested(&ip->i_lock, XFS_ILOCK_DEP(lock_flags));
-       }
+
        xfs_ilock_trace(ip, 1, lock_flags, (inst_t *)__return_address);
 }
 
@@ -631,15 +632,12 @@ xfs_ilock(xfs_inode_t     *ip,
  * lock_flags -- this parameter indicates the inode's locks to be
  *       to be locked.  See the comment for xfs_ilock() for a list
  *      of valid values.
- *
  */
 int
-xfs_ilock_nowait(xfs_inode_t   *ip,
-                uint           lock_flags)
+xfs_ilock_nowait(
+       xfs_inode_t             *ip,
+       uint                    lock_flags)
 {
-       int     iolocked;
-       int     ilocked;
-
        /*
         * You can't set both SHARED and EXCL for the same lock,
         * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED,
@@ -651,37 +649,30 @@ xfs_ilock_nowait(xfs_inode_t      *ip,
               (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
        ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0);
 
-       iolocked = 0;
        if (lock_flags & XFS_IOLOCK_EXCL) {
-               iolocked = mrtryupdate(&ip->i_iolock);
-               if (!iolocked) {
-                       return 0;
-               }
+               if (!mrtryupdate(&ip->i_iolock))
+                       goto out;
        } else if (lock_flags & XFS_IOLOCK_SHARED) {
-               iolocked = mrtryaccess(&ip->i_iolock);
-               if (!iolocked) {
-                       return 0;
-               }
+               if (!mrtryaccess(&ip->i_iolock))
+                       goto out;
        }
        if (lock_flags & XFS_ILOCK_EXCL) {
-               ilocked = mrtryupdate(&ip->i_lock);
-               if (!ilocked) {
-                       if (iolocked) {
-                               mrunlock(&ip->i_iolock);
-                       }
-                       return 0;
-               }
+               if (!mrtryupdate(&ip->i_lock))
+                       goto out_undo_iolock;
        } else if (lock_flags & XFS_ILOCK_SHARED) {
-               ilocked = mrtryaccess(&ip->i_lock);
-               if (!ilocked) {
-                       if (iolocked) {
-                               mrunlock(&ip->i_iolock);
-                       }
-                       return 0;
-               }
+               if (!mrtryaccess(&ip->i_lock))
+                       goto out_undo_iolock;
        }
        xfs_ilock_trace(ip, 2, lock_flags, (inst_t *)__return_address);
        return 1;
+
+ out_undo_iolock:
+       if (lock_flags & XFS_IOLOCK_EXCL)
+               mrunlock_excl(&ip->i_iolock);
+       else if (lock_flags & XFS_IOLOCK_SHARED)
+               mrunlock_shared(&ip->i_iolock);
+ out:
+       return 0;
 }
 
 /*
@@ -697,8 +688,9 @@ xfs_ilock_nowait(xfs_inode_t        *ip,
  *
  */
 void
-xfs_iunlock(xfs_inode_t        *ip,
-           uint        lock_flags)
+xfs_iunlock(
+       xfs_inode_t             *ip,
+       uint                    lock_flags)
 {
        /*
         * You can't set both SHARED and EXCL for the same lock,
@@ -713,31 +705,25 @@ xfs_iunlock(xfs_inode_t   *ip,
                        XFS_LOCK_DEP_MASK)) == 0);
        ASSERT(lock_flags != 0);
 
-       if (lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) {
-               ASSERT(!(lock_flags & XFS_IOLOCK_SHARED) ||
-                      (ismrlocked(&ip->i_iolock, MR_ACCESS)));
-               ASSERT(!(lock_flags & XFS_IOLOCK_EXCL) ||
-                      (ismrlocked(&ip->i_iolock, MR_UPDATE)));
-               mrunlock(&ip->i_iolock);
-       }
+       if (lock_flags & XFS_IOLOCK_EXCL)
+               mrunlock_excl(&ip->i_iolock);
+       else if (lock_flags & XFS_IOLOCK_SHARED)
+               mrunlock_shared(&ip->i_iolock);
 
-       if (lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) {
-               ASSERT(!(lock_flags & XFS_ILOCK_SHARED) ||
-                      (ismrlocked(&ip->i_lock, MR_ACCESS)));
-               ASSERT(!(lock_flags & XFS_ILOCK_EXCL) ||
-                      (ismrlocked(&ip->i_lock, MR_UPDATE)));
-               mrunlock(&ip->i_lock);
+       if (lock_flags & XFS_ILOCK_EXCL)
+               mrunlock_excl(&ip->i_lock);
+       else if (lock_flags & XFS_ILOCK_SHARED)
+               mrunlock_shared(&ip->i_lock);
 
+       if ((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) &&
+           !(lock_flags & XFS_IUNLOCK_NONOTIFY) && ip->i_itemp) {
                /*
                 * Let the AIL know that this item has been unlocked in case
                 * it is in the AIL and anyone is waiting on it.  Don't do
                 * this if the caller has asked us not to.
                 */
-               if (!(lock_flags & XFS_IUNLOCK_NONOTIFY) &&
-                    ip->i_itemp != NULL) {
-                       xfs_trans_unlocked_item(ip->i_mount,
-                                               (xfs_log_item_t*)(ip->i_itemp));
-               }
+               xfs_trans_unlocked_item(ip->i_mount,
+                                       (xfs_log_item_t*)(ip->i_itemp));
        }
        xfs_ilock_trace(ip, 3, lock_flags, (inst_t *)__return_address);
 }
@@ -747,21 +733,47 @@ xfs_iunlock(xfs_inode_t   *ip,
  * if it is being demoted.
  */
 void
-xfs_ilock_demote(xfs_inode_t   *ip,
-                uint           lock_flags)
+xfs_ilock_demote(
+       xfs_inode_t             *ip,
+       uint                    lock_flags)
 {
        ASSERT(lock_flags & (XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL));
        ASSERT((lock_flags & ~(XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL)) == 0);
 
-       if (lock_flags & XFS_ILOCK_EXCL) {
-               ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
+       if (lock_flags & XFS_ILOCK_EXCL)
                mrdemote(&ip->i_lock);
-       }
-       if (lock_flags & XFS_IOLOCK_EXCL) {
-               ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE));
+       if (lock_flags & XFS_IOLOCK_EXCL)
                mrdemote(&ip->i_iolock);
+}
+
+#ifdef DEBUG
+/*
+ * Debug-only routine, without additional rw_semaphore APIs, we can
+ * now only answer requests regarding whether we hold the lock for write
+ * (reader state is outside our visibility, we only track writer state).
+ *
+ * Note: this means !xfs_isilocked would give false positives, so don't do that.
+ */
+int
+xfs_isilocked(
+       xfs_inode_t             *ip,
+       uint                    lock_flags)
+{
+       if ((lock_flags & (XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)) ==
+                       XFS_ILOCK_EXCL) {
+               if (!ip->i_lock.mr_writer)
+                       return 0;
        }
+
+       if ((lock_flags & (XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED)) ==
+                       XFS_IOLOCK_EXCL) {
+               if (!ip->i_iolock.mr_writer)
+                       return 0;
+       }
+
+       return 1;
 }
+#endif
 
 /*
  * The following three routines simply manage the i_flock
index ca12acb90394193571f4b09f9febba47ac091ea7..cf0bb9c1d621fb702897acdfd41bed22cabf8e67 100644 (file)
@@ -1291,7 +1291,7 @@ xfs_file_last_byte(
        xfs_fileoff_t   size_last_block;
        int             error;
 
-       ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE | MR_ACCESS));
+       ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED));
 
        mp = ip->i_mount;
        /*
@@ -1402,7 +1402,7 @@ xfs_itruncate_start(
        bhv_vnode_t     *vp;
        int             error = 0;
 
-       ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE) != 0);
+       ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
        ASSERT((new_size == 0) || (new_size <= ip->i_size));
        ASSERT((flags == XFS_ITRUNC_DEFINITE) ||
               (flags == XFS_ITRUNC_MAYBE));
@@ -1528,8 +1528,7 @@ xfs_itruncate_finish(
        xfs_bmap_free_t free_list;
        int             error;
 
-       ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE) != 0);
-       ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0);
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
        ASSERT((new_size == 0) || (new_size <= ip->i_size));
        ASSERT(*tp != NULL);
        ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
@@ -1780,8 +1779,7 @@ xfs_igrow_start(
        xfs_fsize_t     new_size,
        cred_t          *credp)
 {
-       ASSERT(ismrlocked(&(ip->i_lock), MR_UPDATE) != 0);
-       ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE) != 0);
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
        ASSERT(new_size > ip->i_size);
 
        /*
@@ -1809,8 +1807,7 @@ xfs_igrow_finish(
        xfs_fsize_t     new_size,
        int             change_flag)
 {
-       ASSERT(ismrlocked(&(ip->i_lock), MR_UPDATE) != 0);
-       ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE) != 0);
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
        ASSERT(ip->i_transp == tp);
        ASSERT(new_size > ip->i_size);
 
@@ -2287,7 +2284,7 @@ xfs_ifree(
        xfs_dinode_t            *dip;
        xfs_buf_t               *ibp;
 
-       ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        ASSERT(ip->i_transp == tp);
        ASSERT(ip->i_d.di_nlink == 0);
        ASSERT(ip->i_d.di_nextents == 0);
@@ -2746,7 +2743,7 @@ void
 xfs_ipin(
        xfs_inode_t     *ip)
 {
-       ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 
        atomic_inc(&ip->i_pincount);
 }
@@ -2779,7 +2776,7 @@ __xfs_iunpin_wait(
 {
        xfs_inode_log_item_t    *iip = ip->i_itemp;
 
-       ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE | MR_ACCESS));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
        if (atomic_read(&ip->i_pincount) == 0)
                return;
 
@@ -2829,7 +2826,7 @@ xfs_iextents_copy(
        xfs_fsblock_t           start_block;
 
        ifp = XFS_IFORK_PTR(ip, whichfork);
-       ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
        ASSERT(ifp->if_bytes > 0);
 
        nrecs = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
@@ -3132,7 +3129,7 @@ xfs_iflush(
 
        XFS_STATS_INC(xs_iflush_count);
 
-       ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
        ASSERT(issemalocked(&(ip->i_flock)));
        ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
               ip->i_d.di_nextents > ip->i_df.if_ext_max);
@@ -3297,7 +3294,7 @@ xfs_iflush_int(
        int                     first;
 #endif
 
-       ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
        ASSERT(issemalocked(&(ip->i_flock)));
        ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
               ip->i_d.di_nextents > ip->i_df.if_ext_max);
index 93c37697a72c6b0cf7f83501c26633e1afd0969c..0a999fee4f03e343e4038e9e818464e3bf06b83d 100644 (file)
@@ -386,20 +386,9 @@ xfs_iflags_test_and_clear(xfs_inode_t *ip, unsigned short flags)
 #define        XFS_ILOCK_EXCL          (1<<2)
 #define        XFS_ILOCK_SHARED        (1<<3)
 #define        XFS_IUNLOCK_NONOTIFY    (1<<4)
-/*     #define XFS_IOLOCK_NESTED       (1<<5)  */
-#define XFS_EXTENT_TOKEN_RD    (1<<6)
-#define XFS_SIZE_TOKEN_RD      (1<<7)
-#define XFS_EXTSIZE_RD         (XFS_EXTENT_TOKEN_RD|XFS_SIZE_TOKEN_RD)
-#define XFS_WILLLEND           (1<<8)  /* Always acquire tokens for lending */
-#define XFS_EXTENT_TOKEN_WR    (XFS_EXTENT_TOKEN_RD | XFS_WILLLEND)
-#define XFS_SIZE_TOKEN_WR       (XFS_SIZE_TOKEN_RD | XFS_WILLLEND)
-#define XFS_EXTSIZE_WR         (XFS_EXTSIZE_RD | XFS_WILLLEND)
-/* TODO:XFS_SIZE_TOKEN_WANT    (1<<9) */
 
 #define XFS_LOCK_MASK          (XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED \
-                               | XFS_ILOCK_EXCL | XFS_ILOCK_SHARED \
-                               | XFS_EXTENT_TOKEN_RD | XFS_SIZE_TOKEN_RD \
-                               | XFS_WILLLEND)
+                               | XFS_ILOCK_EXCL | XFS_ILOCK_SHARED)
 
 /*
  * Flags for lockdep annotations.
@@ -483,6 +472,7 @@ void                xfs_ilock(xfs_inode_t *, uint);
 int            xfs_ilock_nowait(xfs_inode_t *, uint);
 void           xfs_iunlock(xfs_inode_t *, uint);
 void           xfs_ilock_demote(xfs_inode_t *, uint);
+int            xfs_isilocked(xfs_inode_t *, uint);
 void           xfs_iflock(xfs_inode_t *);
 int            xfs_iflock_nowait(xfs_inode_t *);
 uint           xfs_ilock_map_shared(xfs_inode_t *);
@@ -534,7 +524,7 @@ int         xfs_iflush(xfs_inode_t *, uint);
 void           xfs_iflush_all(struct xfs_mount *);
 void           xfs_ichgtime(xfs_inode_t *, int);
 xfs_fsize_t    xfs_file_last_byte(xfs_inode_t *);
-void           xfs_lock_inodes(xfs_inode_t **, int, int, uint);
+void           xfs_lock_inodes(xfs_inode_t **, int, uint);
 
 void           xfs_synchronize_atime(xfs_inode_t *);
 void           xfs_mark_inode_dirty_sync(xfs_inode_t *);
index 93b5db453ea296da3cb64ac7e9b49a63a77fc1b0..167b33f15772c395c1f5d3260bf1e2d36d666c39 100644 (file)
@@ -547,7 +547,7 @@ STATIC void
 xfs_inode_item_pin(
        xfs_inode_log_item_t    *iip)
 {
-       ASSERT(ismrlocked(&(iip->ili_inode->i_lock), MR_UPDATE));
+       ASSERT(xfs_isilocked(iip->ili_inode, XFS_ILOCK_EXCL));
        xfs_ipin(iip->ili_inode);
 }
 
@@ -664,13 +664,13 @@ xfs_inode_item_unlock(
 
        ASSERT(iip != NULL);
        ASSERT(iip->ili_inode->i_itemp != NULL);
-       ASSERT(ismrlocked(&(iip->ili_inode->i_lock), MR_UPDATE));
+       ASSERT(xfs_isilocked(iip->ili_inode, XFS_ILOCK_EXCL));
        ASSERT((!(iip->ili_inode->i_itemp->ili_flags &
                  XFS_ILI_IOLOCKED_EXCL)) ||
-              ismrlocked(&(iip->ili_inode->i_iolock), MR_UPDATE));
+              xfs_isilocked(iip->ili_inode, XFS_IOLOCK_EXCL));
        ASSERT((!(iip->ili_inode->i_itemp->ili_flags &
                  XFS_ILI_IOLOCKED_SHARED)) ||
-              ismrlocked(&(iip->ili_inode->i_iolock), MR_ACCESS));
+              xfs_isilocked(iip->ili_inode, XFS_IOLOCK_SHARED));
        /*
         * Clear the transaction pointer in the inode.
         */
@@ -769,7 +769,7 @@ xfs_inode_item_pushbuf(
 
        ip = iip->ili_inode;
 
-       ASSERT(ismrlocked(&(ip->i_lock), MR_ACCESS));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED));
 
        /*
         * The ili_pushbuf_flag keeps others from
@@ -857,7 +857,7 @@ xfs_inode_item_push(
 
        ip = iip->ili_inode;
 
-       ASSERT(ismrlocked(&(ip->i_lock), MR_ACCESS));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED));
        ASSERT(issemalocked(&(ip->i_flock)));
        /*
         * Since we were able to lock the inode's flush lock and
index fb3cf11914195ce85dbea2f5bf90ff3dde668bf4..7edcde691d1a2539e340db2e83769ad12188e6e6 100644 (file)
@@ -196,14 +196,14 @@ xfs_iomap(
                break;
        case BMAPI_WRITE:
                xfs_iomap_enter_trace(XFS_IOMAP_WRITE_ENTER, ip, offset, count);
-               lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR;
+               lockmode = XFS_ILOCK_EXCL;
                if (flags & BMAPI_IGNSTATE)
                        bmapi_flags |= XFS_BMAPI_IGSTATE|XFS_BMAPI_ENTIRE;
                xfs_ilock(ip, lockmode);
                break;
        case BMAPI_ALLOCATE:
                xfs_iomap_enter_trace(XFS_IOMAP_ALLOC_ENTER, ip, offset, count);
-               lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD;
+               lockmode = XFS_ILOCK_SHARED;
                bmapi_flags = XFS_BMAPI_ENTIRE;
 
                /* Attempt non-blocking lock */
@@ -523,8 +523,7 @@ xfs_iomap_write_direct(
                goto error_out;
        }
 
-       if (unlikely(!imap.br_startblock &&
-                    !(XFS_IS_REALTIME_INODE(ip)))) {
+       if (!(imap.br_startblock || XFS_IS_REALTIME_INODE(ip))) {
                error = xfs_cmn_err_fsblock_zero(ip, &imap);
                goto error_out;
        }
@@ -624,7 +623,7 @@ xfs_iomap_write_delay(
        int             prealloc, fsynced = 0;
        int             error;
 
-       ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE) != 0);
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 
        /*
         * Make sure that the dquots are there. This doesn't hold
@@ -686,8 +685,7 @@ retry:
                goto retry;
        }
 
-       if (unlikely(!imap[0].br_startblock &&
-                    !(XFS_IS_REALTIME_INODE(ip))))
+       if (!(imap[0].br_startblock || XFS_IS_REALTIME_INODE(ip)))
                return xfs_cmn_err_fsblock_zero(ip, &imap[0]);
 
        *ret_imap = imap[0];
@@ -838,9 +836,9 @@ xfs_iomap_write_allocate(
                 * See if we were able to allocate an extent that
                 * covers at least part of the callers request
                 */
-               if (unlikely(!imap.br_startblock &&
-                            XFS_IS_REALTIME_INODE(ip)))
+               if (!(imap.br_startblock || XFS_IS_REALTIME_INODE(ip)))
                        return xfs_cmn_err_fsblock_zero(ip, &imap);
+
                if ((offset_fsb >= imap.br_startoff) &&
                    (offset_fsb < (imap.br_startoff +
                                   imap.br_blockcount))) {
@@ -934,8 +932,7 @@ xfs_iomap_write_unwritten(
                if (error)
                        return XFS_ERROR(error);
 
-               if (unlikely(!imap.br_startblock &&
-                            !(XFS_IS_REALTIME_INODE(ip))))
+               if (!(imap.br_startblock || XFS_IS_REALTIME_INODE(ip)))
                        return xfs_cmn_err_fsblock_zero(ip, &imap);
 
                if ((numblks_fsb = imap.br_blockcount) == 0) {
index eb85bdedad0c7505aa90bdeb09c97403b3979631..419de15aeb43f004f3ae1e67ef37676a3e2f8629 100644 (file)
@@ -71,11 +71,6 @@ xfs_bulkstat_one_iget(
 
        ASSERT(ip != NULL);
        ASSERT(ip->i_blkno != (xfs_daddr_t)0);
-       if (ip->i_d.di_mode == 0) {
-               *stat = BULKSTAT_RV_NOTHING;
-               error = XFS_ERROR(ENOENT);
-               goto out_iput;
-       }
 
        vp = XFS_ITOV(ip);
        dic = &ip->i_d;
@@ -124,7 +119,6 @@ xfs_bulkstat_one_iget(
                break;
        }
 
- out_iput:
        xfs_iput(ip, XFS_ILOCK_SHARED);
        return error;
 }
index 2fec452afbcc8a710ff3db930cf21f0f289d56f4..da3988453b712b0c64d3afc00f6fc159271c34cf 100644 (file)
@@ -54,8 +54,9 @@ STATIC void   xfs_unmountfs_wait(xfs_mount_t *);
 #ifdef HAVE_PERCPU_SB
 STATIC void    xfs_icsb_destroy_counters(xfs_mount_t *);
 STATIC void    xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t,
-                                               int, int);
-STATIC void    xfs_icsb_sync_counters(xfs_mount_t *);
+                                               int);
+STATIC void    xfs_icsb_balance_counter_locked(xfs_mount_t *, xfs_sb_field_t,
+                                               int);
 STATIC int     xfs_icsb_modify_counters(xfs_mount_t *, xfs_sb_field_t,
                                                int64_t, int);
 STATIC void    xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t);
@@ -63,8 +64,8 @@ STATIC void   xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t);
 #else
 
 #define xfs_icsb_destroy_counters(mp)                  do { } while (0)
-#define xfs_icsb_balance_counter(mp, a, b, c)          do { } while (0)
-#define xfs_icsb_sync_counters(mp)                     do { } while (0)
+#define xfs_icsb_balance_counter(mp, a, b)             do { } while (0)
+#define xfs_icsb_balance_counter_locked(mp, a, b)      do { } while (0)
 #define xfs_icsb_modify_counters(mp, a, b, c)          do { } while (0)
 
 #endif
@@ -1400,7 +1401,7 @@ xfs_log_sbcount(
        if (!xfs_fs_writable(mp))
                return 0;
 
-       xfs_icsb_sync_counters(mp);
+       xfs_icsb_sync_counters(mp, 0);
 
        /*
         * we don't need to do this if we are updating the superblock
@@ -2026,9 +2027,9 @@ xfs_icsb_cpu_notify(
        case CPU_ONLINE:
        case CPU_ONLINE_FROZEN:
                xfs_icsb_lock(mp);
-               xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0, 0);
-               xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0, 0);
-               xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0, 0);
+               xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
+               xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
+               xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
                xfs_icsb_unlock(mp);
                break;
        case CPU_DEAD:
@@ -2048,12 +2049,9 @@ xfs_icsb_cpu_notify(
 
                memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
 
-               xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT,
-                                        XFS_ICSB_SB_LOCKED, 0);
-               xfs_icsb_balance_counter(mp, XFS_SBS_IFREE,
-                                        XFS_ICSB_SB_LOCKED, 0);
-               xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS,
-                                        XFS_ICSB_SB_LOCKED, 0);
+               xfs_icsb_balance_counter_locked(mp, XFS_SBS_ICOUNT, 0);
+               xfs_icsb_balance_counter_locked(mp, XFS_SBS_IFREE, 0);
+               xfs_icsb_balance_counter_locked(mp, XFS_SBS_FDBLOCKS, 0);
                spin_unlock(&mp->m_sb_lock);
                xfs_icsb_unlock(mp);
                break;
@@ -2105,9 +2103,9 @@ xfs_icsb_reinit_counters(
         * initial balance kicks us off correctly
         */
        mp->m_icsb_counters = -1;
-       xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0, 0);
-       xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0, 0);
-       xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0, 0);
+       xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
+       xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
+       xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
        xfs_icsb_unlock(mp);
 }
 
@@ -2223,7 +2221,7 @@ xfs_icsb_disable_counter(
        if (!test_and_set_bit(field, &mp->m_icsb_counters)) {
                /* drain back to superblock */
 
-               xfs_icsb_count(mp, &cnt, XFS_ICSB_SB_LOCKED|XFS_ICSB_LAZY_COUNT);
+               xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT);
                switch(field) {
                case XFS_SBS_ICOUNT:
                        mp->m_sb.sb_icount = cnt.icsb_icount;
@@ -2278,38 +2276,33 @@ xfs_icsb_enable_counter(
 }
 
 void
-xfs_icsb_sync_counters_flags(
+xfs_icsb_sync_counters_locked(
        xfs_mount_t     *mp,
        int             flags)
 {
        xfs_icsb_cnts_t cnt;
 
-       /* Pass 1: lock all counters */
-       if ((flags & XFS_ICSB_SB_LOCKED) == 0)
-               spin_lock(&mp->m_sb_lock);
-
        xfs_icsb_count(mp, &cnt, flags);
 
-       /* Step 3: update mp->m_sb fields */
        if (!xfs_icsb_counter_disabled(mp, XFS_SBS_ICOUNT))
                mp->m_sb.sb_icount = cnt.icsb_icount;
        if (!xfs_icsb_counter_disabled(mp, XFS_SBS_IFREE))
                mp->m_sb.sb_ifree = cnt.icsb_ifree;
        if (!xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS))
                mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
-
-       if ((flags & XFS_ICSB_SB_LOCKED) == 0)
-               spin_unlock(&mp->m_sb_lock);
 }
 
 /*
  * Accurate update of per-cpu counters to incore superblock
  */
-STATIC void
+void
 xfs_icsb_sync_counters(
-       xfs_mount_t     *mp)
+       xfs_mount_t     *mp,
+       int             flags)
 {
-       xfs_icsb_sync_counters_flags(mp, 0);
+       spin_lock(&mp->m_sb_lock);
+       xfs_icsb_sync_counters_locked(mp, flags);
+       spin_unlock(&mp->m_sb_lock);
 }
 
 /*
@@ -2332,19 +2325,15 @@ xfs_icsb_sync_counters(
 #define XFS_ICSB_FDBLK_CNTR_REENABLE(mp) \
                (uint64_t)(512 + XFS_ALLOC_SET_ASIDE(mp))
 STATIC void
-xfs_icsb_balance_counter(
+xfs_icsb_balance_counter_locked(
        xfs_mount_t     *mp,
        xfs_sb_field_t  field,
-       int             flags,
        int             min_per_cpu)
 {
        uint64_t        count, resid;
        int             weight = num_online_cpus();
        uint64_t        min = (uint64_t)min_per_cpu;
 
-       if (!(flags & XFS_ICSB_SB_LOCKED))
-               spin_lock(&mp->m_sb_lock);
-
        /* disable counter and sync counter */
        xfs_icsb_disable_counter(mp, field);
 
@@ -2354,19 +2343,19 @@ xfs_icsb_balance_counter(
                count = mp->m_sb.sb_icount;
                resid = do_div(count, weight);
                if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
-                       goto out;
+                       return;
                break;
        case XFS_SBS_IFREE:
                count = mp->m_sb.sb_ifree;
                resid = do_div(count, weight);
                if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
-                       goto out;
+                       return;
                break;
        case XFS_SBS_FDBLOCKS:
                count = mp->m_sb.sb_fdblocks;
                resid = do_div(count, weight);
                if (count < max(min, XFS_ICSB_FDBLK_CNTR_REENABLE(mp)))
-                       goto out;
+                       return;
                break;
        default:
                BUG();
@@ -2375,9 +2364,17 @@ xfs_icsb_balance_counter(
        }
 
        xfs_icsb_enable_counter(mp, field, count, resid);
-out:
-       if (!(flags & XFS_ICSB_SB_LOCKED))
-               spin_unlock(&mp->m_sb_lock);
+}
+
+STATIC void
+xfs_icsb_balance_counter(
+       xfs_mount_t     *mp,
+       xfs_sb_field_t  fields,
+       int             min_per_cpu)
+{
+       spin_lock(&mp->m_sb_lock);
+       xfs_icsb_balance_counter_locked(mp, fields, min_per_cpu);
+       spin_unlock(&mp->m_sb_lock);
 }
 
 STATIC int
@@ -2484,7 +2481,7 @@ slow_path:
         * we are done.
         */
        if (ret != ENOSPC)
-               xfs_icsb_balance_counter(mp, field, 0, 0);
+               xfs_icsb_balance_counter(mp, field, 0);
        xfs_icsb_unlock(mp);
        return ret;
 
@@ -2508,7 +2505,7 @@ balance_counter:
         * will either succeed through the fast path or slow path without
         * another balance operation being required.
         */
-       xfs_icsb_balance_counter(mp, field, 0, delta);
+       xfs_icsb_balance_counter(mp, field, delta);
        xfs_icsb_unlock(mp);
        goto again;
 }
index 1ed575110ff0149084cc46fee7014b8294817919..63e0693a358a295e4657eabde52ebc88b8de965e 100644 (file)
@@ -206,17 +206,18 @@ typedef struct xfs_icsb_cnts {
 
 #define XFS_ICSB_FLAG_LOCK     (1 << 0)        /* counter lock bit */
 
-#define XFS_ICSB_SB_LOCKED     (1 << 0)        /* sb already locked */
 #define XFS_ICSB_LAZY_COUNT    (1 << 1)        /* accuracy not needed */
 
 extern int     xfs_icsb_init_counters(struct xfs_mount *);
 extern void    xfs_icsb_reinit_counters(struct xfs_mount *);
-extern void    xfs_icsb_sync_counters_flags(struct xfs_mount *, int);
+extern void    xfs_icsb_sync_counters(struct xfs_mount *, int);
+extern void    xfs_icsb_sync_counters_locked(struct xfs_mount *, int);
 
 #else
 #define xfs_icsb_init_counters(mp)     (0)
 #define xfs_icsb_reinit_counters(mp)   do { } while (0)
-#define xfs_icsb_sync_counters_flags(mp, flags)        do { } while (0)
+#define xfs_icsb_sync_counters(mp, flags)      do { } while (0)
+#define xfs_icsb_sync_counters_locked(mp, flags) do { } while (0)
 #endif
 
 typedef struct xfs_ail {
index ee371890d85db6b20b73627c510baab2563b69fd..d8063e1ad2987e94470a9ff24cff44dece1c5f0d 100644 (file)
@@ -55,85 +55,32 @@ xfs_rename_unlock4(
 
        xfs_iunlock(i_tab[0], lock_mode);
        for (i = 1; i < 4; i++) {
-               if (i_tab[i] == NULL) {
+               if (i_tab[i] == NULL)
                        break;
-               }
+
                /*
                 * Watch out for duplicate entries in the table.
                 */
-               if (i_tab[i] != i_tab[i-1]) {
+               if (i_tab[i] != i_tab[i-1])
                        xfs_iunlock(i_tab[i], lock_mode);
-               }
        }
 }
 
-#ifdef DEBUG
-int xfs_rename_skip, xfs_rename_nskip;
-#endif
-
 /*
- * The following routine will acquire the locks required for a rename
- * operation. The code understands the semantics of renames and will
- * validate that name1 exists under dp1 & that name2 may or may not
- * exist under dp2.
- *
- * We are renaming dp1/name1 to dp2/name2.
- *
- * Return ENOENT if dp1 does not exist, other lookup errors, or 0 for success.
+ * Enter all inodes for a rename transaction into a sorted array.
  */
-STATIC int
-xfs_lock_for_rename(
+STATIC void
+xfs_sort_for_rename(
        xfs_inode_t     *dp1,   /* in: old (source) directory inode */
        xfs_inode_t     *dp2,   /* in: new (target) directory inode */
        xfs_inode_t     *ip1,   /* in: inode of old entry */
-       struct xfs_name *name2, /* in: new entry name */
-       xfs_inode_t     **ipp2, /* out: inode of new entry, if it
+       xfs_inode_t     *ip2,   /* in: inode of new entry, if it
                                   already exists, NULL otherwise. */
        xfs_inode_t     **i_tab,/* out: array of inode returned, sorted */
        int             *num_inodes)  /* out: number of inodes in array */
 {
-       xfs_inode_t             *ip2 = NULL;
        xfs_inode_t             *temp;
-       xfs_ino_t               inum1, inum2;
-       int                     error;
        int                     i, j;
-       uint                    lock_mode;
-       int                     diff_dirs = (dp1 != dp2);
-
-       /*
-        * First, find out the current inums of the entries so that we
-        * can determine the initial locking order.  We'll have to
-        * sanity check stuff after all the locks have been acquired
-        * to see if we still have the right inodes, directories, etc.
-        */
-       lock_mode = xfs_ilock_map_shared(dp1);
-       IHOLD(ip1);
-       xfs_itrace_ref(ip1);
-
-       inum1 = ip1->i_ino;
-
-       /*
-        * Unlock dp1 and lock dp2 if they are different.
-        */
-       if (diff_dirs) {
-               xfs_iunlock_map_shared(dp1, lock_mode);
-               lock_mode = xfs_ilock_map_shared(dp2);
-       }
-
-       error = xfs_dir_lookup_int(dp2, lock_mode, name2, &inum2, &ip2);
-       if (error == ENOENT) {          /* target does not need to exist. */
-               inum2 = 0;
-       } else if (error) {
-               /*
-                * If dp2 and dp1 are the same, the next line unlocks dp1.
-                * Got it?
-                */
-               xfs_iunlock_map_shared(dp2, lock_mode);
-               IRELE (ip1);
-               return error;
-       } else {
-               xfs_itrace_ref(ip2);
-       }
 
        /*
         * i_tab contains a list of pointers to inodes.  We initialize
@@ -145,21 +92,20 @@ xfs_lock_for_rename(
        i_tab[0] = dp1;
        i_tab[1] = dp2;
        i_tab[2] = ip1;
-       if (inum2 == 0) {
-               *num_inodes = 3;
-               i_tab[3] = NULL;
-       } else {
+       if (ip2) {
                *num_inodes = 4;
                i_tab[3] = ip2;
+       } else {
+               *num_inodes = 3;
+               i_tab[3] = NULL;
        }
-       *ipp2 = i_tab[3];
 
        /*
         * Sort the elements via bubble sort.  (Remember, there are at
         * most 4 elements to sort, so this is adequate.)
         */
-       for (i=0; i < *num_inodes; i++) {
-               for (j=1; j < *num_inodes; j++) {
+       for (i = 0; i < *num_inodes; i++) {
+               for (j = 1; j < *num_inodes; j++) {
                        if (i_tab[j]->i_ino < i_tab[j-1]->i_ino) {
                                temp = i_tab[j];
                                i_tab[j] = i_tab[j-1];
@@ -167,30 +113,6 @@ xfs_lock_for_rename(
                        }
                }
        }
-
-       /*
-        * We have dp2 locked. If it isn't first, unlock it.
-        * If it is first, tell xfs_lock_inodes so it can skip it
-        * when locking. if dp1 == dp2, xfs_lock_inodes will skip both
-        * since they are equal. xfs_lock_inodes needs all these inodes
-        * so that it can unlock and retry if there might be a dead-lock
-        * potential with the log.
-        */
-
-       if (i_tab[0] == dp2 && lock_mode == XFS_ILOCK_SHARED) {
-#ifdef DEBUG
-               xfs_rename_skip++;
-#endif
-               xfs_lock_inodes(i_tab, *num_inodes, 1, XFS_ILOCK_SHARED);
-       } else {
-#ifdef DEBUG
-               xfs_rename_nskip++;
-#endif
-               xfs_iunlock_map_shared(dp2, lock_mode);
-               xfs_lock_inodes(i_tab, *num_inodes, 0, XFS_ILOCK_SHARED);
-       }
-
-       return 0;
 }
 
 /*
@@ -202,10 +124,10 @@ xfs_rename(
        struct xfs_name *src_name,
        xfs_inode_t     *src_ip,
        xfs_inode_t     *target_dp,
-       struct xfs_name *target_name)
+       struct xfs_name *target_name,
+       xfs_inode_t     *target_ip)
 {
-       xfs_trans_t     *tp;
-       xfs_inode_t     *target_ip;
+       xfs_trans_t     *tp = NULL;
        xfs_mount_t     *mp = src_dp->i_mount;
        int             new_parent;             /* moving to a new dir */
        int             src_is_directory;       /* src_name is a directory */
@@ -215,9 +137,7 @@ xfs_rename(
        int             cancel_flags;
        int             committed;
        xfs_inode_t     *inodes[4];
-       int             target_ip_dropped = 0;  /* dropped target_ip link? */
        int             spaceres;
-       int             target_link_zero = 0;
        int             num_inodes;
 
        xfs_itrace_entry(src_dp);
@@ -230,64 +150,27 @@ xfs_rename(
                                        target_dp, DM_RIGHT_NULL,
                                        src_name->name, target_name->name,
                                        0, 0, 0);
-               if (error) {
+               if (error)
                        return error;
-               }
        }
        /* Return through std_return after this point. */
 
-       /*
-        * Lock all the participating inodes. Depending upon whether
-        * the target_name exists in the target directory, and
-        * whether the target directory is the same as the source
-        * directory, we can lock from 2 to 4 inodes.
-        * xfs_lock_for_rename() will return ENOENT if src_name
-        * does not exist in the source directory.
-        */
-       tp = NULL;
-       error = xfs_lock_for_rename(src_dp, target_dp, src_ip, target_name,
-                                       &target_ip, inodes, &num_inodes);
-       if (error) {
-               /*
-                * We have nothing locked, no inode references, and
-                * no transaction, so just get out.
-                */
-               goto std_return;
-       }
-
-       ASSERT(src_ip != NULL);
+       new_parent = (src_dp != target_dp);
+       src_is_directory = ((src_ip->i_d.di_mode & S_IFMT) == S_IFDIR);
 
-       if ((src_ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
+       if (src_is_directory) {
                /*
                 * Check for link count overflow on target_dp
                 */
-               if (target_ip == NULL && (src_dp != target_dp) &&
+               if (target_ip == NULL && new_parent &&
                    target_dp->i_d.di_nlink >= XFS_MAXLINK) {
                        error = XFS_ERROR(EMLINK);
-                       xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED);
-                       goto rele_return;
+                       goto std_return;
                }
        }
 
-       /*
-        * If we are using project inheritance, we only allow renames
-        * into our tree when the project IDs are the same; else the
-        * tree quota mechanism would be circumvented.
-        */
-       if (unlikely((target_dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
-                    (target_dp->i_d.di_projid != src_ip->i_d.di_projid))) {
-               error = XFS_ERROR(EXDEV);
-               xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED);
-               goto rele_return;
-       }
-
-       new_parent = (src_dp != target_dp);
-       src_is_directory = ((src_ip->i_d.di_mode & S_IFMT) == S_IFDIR);
-
-       /*
-        * Drop the locks on our inodes so that we can start the transaction.
-        */
-       xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED);
+       xfs_sort_for_rename(src_dp, target_dp, src_ip, target_ip,
+                               inodes, &num_inodes);
 
        XFS_BMAP_INIT(&free_list, &first_block);
        tp = xfs_trans_alloc(mp, XFS_TRANS_RENAME);
@@ -302,7 +185,7 @@ xfs_rename(
        }
        if (error) {
                xfs_trans_cancel(tp, 0);
-               goto rele_return;
+               goto std_return;
        }
 
        /*
@@ -310,13 +193,29 @@ xfs_rename(
         */
        if ((error = XFS_QM_DQVOPRENAME(mp, inodes))) {
                xfs_trans_cancel(tp, cancel_flags);
-               goto rele_return;
+               goto std_return;
        }
 
        /*
-        * Reacquire the inode locks we dropped above.
+        * Lock all the participating inodes. Depending upon whether
+        * the target_name exists in the target directory, and
+        * whether the target directory is the same as the source
+        * directory, we can lock from 2 to 4 inodes.
+        */
+       xfs_lock_inodes(inodes, num_inodes, XFS_ILOCK_EXCL);
+
+       /*
+        * If we are using project inheritance, we only allow renames
+        * into our tree when the project IDs are the same; else the
+        * tree quota mechanism would be circumvented.
         */
-       xfs_lock_inodes(inodes, num_inodes, 0, XFS_ILOCK_EXCL);
+       if (unlikely((target_dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
+                    (target_dp->i_d.di_projid != src_ip->i_d.di_projid))) {
+               error = XFS_ERROR(EXDEV);
+               xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED);
+               xfs_trans_cancel(tp, cancel_flags);
+               goto std_return;
+       }
 
        /*
         * Join all the inodes to the transaction. From this point on,
@@ -328,17 +227,17 @@ xfs_rename(
         */
        IHOLD(src_dp);
        xfs_trans_ijoin(tp, src_dp, XFS_ILOCK_EXCL);
+
        if (new_parent) {
                IHOLD(target_dp);
                xfs_trans_ijoin(tp, target_dp, XFS_ILOCK_EXCL);
        }
-       if ((src_ip != src_dp) && (src_ip != target_dp)) {
-               xfs_trans_ijoin(tp, src_ip, XFS_ILOCK_EXCL);
-       }
-       if ((target_ip != NULL) &&
-           (target_ip != src_ip) &&
-           (target_ip != src_dp) &&
-           (target_ip != target_dp)) {
+
+       IHOLD(src_ip);
+       xfs_trans_ijoin(tp, src_ip, XFS_ILOCK_EXCL);
+
+       if (target_ip) {
+               IHOLD(target_ip);
                xfs_trans_ijoin(tp, target_ip, XFS_ILOCK_EXCL);
        }
 
@@ -412,7 +311,6 @@ xfs_rename(
                error = xfs_droplink(tp, target_ip);
                if (error)
                        goto abort_return;
-               target_ip_dropped = 1;
 
                if (src_is_directory) {
                        /*
@@ -422,10 +320,6 @@ xfs_rename(
                        if (error)
                                goto abort_return;
                }
-
-               /* Do this test while we still hold the locks */
-               target_link_zero = (target_ip)->i_d.di_nlink==0;
-
        } /* target_ip != NULL */
 
        /*
@@ -491,15 +385,6 @@ xfs_rename(
                xfs_trans_log_inode(tp, target_dp, XFS_ILOG_CORE);
        }
 
-       /*
-        * If there was a target inode, take an extra reference on
-        * it here so that it doesn't go to xfs_inactive() from
-        * within the commit.
-        */
-       if (target_ip != NULL) {
-               IHOLD(target_ip);
-       }
-
        /*
         * If this is a synchronous mount, make sure that the
         * rename transaction goes to disk before returning to
@@ -509,30 +394,11 @@ xfs_rename(
                xfs_trans_set_sync(tp);
        }
 
-       /*
-        * Take refs. for vop_link_removed calls below.  No need to worry
-        * about directory refs. because the caller holds them.
-        *
-        * Do holds before the xfs_bmap_finish since it might rele them down
-        * to zero.
-        */
-
-       if (target_ip_dropped)
-               IHOLD(target_ip);
-       IHOLD(src_ip);
-
        error = xfs_bmap_finish(&tp, &free_list, &committed);
        if (error) {
                xfs_bmap_cancel(&free_list);
                xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES |
                                 XFS_TRANS_ABORT));
-               if (target_ip != NULL) {
-                       IRELE(target_ip);
-               }
-               if (target_ip_dropped) {
-                       IRELE(target_ip);
-               }
-               IRELE(src_ip);
                goto std_return;
        }
 
@@ -541,15 +407,6 @@ xfs_rename(
         * the vnode references.
         */
        error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
-       if (target_ip != NULL)
-               IRELE(target_ip);
-       /*
-        * Let interposed file systems know about removed links.
-        */
-       if (target_ip_dropped)
-               IRELE(target_ip);
-
-       IRELE(src_ip);
 
        /* Fall through to std_return with error = 0 or errno from
         * xfs_trans_commit      */
@@ -571,11 +428,4 @@ std_return:
        xfs_bmap_cancel(&free_list);
        xfs_trans_cancel(tp, cancel_flags);
        goto std_return;
-
- rele_return:
-       IRELE(src_ip);
-       if (target_ip != NULL) {
-               IRELE(target_ip);
-       }
-       goto std_return;
 }
index b8db1d5cde5a1fac03837ae85f130c7091775925..4c70bf5e9985a8145a65b2a3670e41a5ca42ab8a 100644 (file)
@@ -111,13 +111,13 @@ xfs_trans_iget(
                 */
                ASSERT(ip->i_itemp != NULL);
                ASSERT(lock_flags & XFS_ILOCK_EXCL);
-               ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
+               ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
                ASSERT((!(lock_flags & XFS_IOLOCK_EXCL)) ||
-                      ismrlocked(&ip->i_iolock, MR_UPDATE));
+                      xfs_isilocked(ip, XFS_IOLOCK_EXCL));
                ASSERT((!(lock_flags & XFS_IOLOCK_EXCL)) ||
                       (ip->i_itemp->ili_flags & XFS_ILI_IOLOCKED_EXCL));
                ASSERT((!(lock_flags & XFS_IOLOCK_SHARED)) ||
-                      ismrlocked(&ip->i_iolock, (MR_UPDATE | MR_ACCESS)));
+                      xfs_isilocked(ip, XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED));
                ASSERT((!(lock_flags & XFS_IOLOCK_SHARED)) ||
                       (ip->i_itemp->ili_flags & XFS_ILI_IOLOCKED_ANY));
 
@@ -185,7 +185,7 @@ xfs_trans_ijoin(
        xfs_inode_log_item_t    *iip;
 
        ASSERT(ip->i_transp == NULL);
-       ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        ASSERT(lock_flags & XFS_ILOCK_EXCL);
        if (ip->i_itemp == NULL)
                xfs_inode_item_init(ip, ip->i_mount);
@@ -232,7 +232,7 @@ xfs_trans_ihold(
 {
        ASSERT(ip->i_transp == tp);
        ASSERT(ip->i_itemp != NULL);
-       ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 
        ip->i_itemp->ili_flags |= XFS_ILI_HOLD;
 }
@@ -257,7 +257,7 @@ xfs_trans_log_inode(
 
        ASSERT(ip->i_transp == tp);
        ASSERT(ip->i_itemp != NULL);
-       ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 
        lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)(ip->i_itemp));
        ASSERT(lidp != NULL);
index 2b8dc7e40772efc5829fed46870fa16b0005f675..98e5f110ba5f412be32adcc9a2be9205190da9e5 100644 (file)
 #include "xfs_utils.h"
 
 
-int
-xfs_dir_lookup_int(
-       xfs_inode_t     *dp,
-       uint            lock_mode,
-       struct xfs_name *name,
-       xfs_ino_t       *inum,
-       xfs_inode_t     **ipp)
-{
-       int             error;
-
-       xfs_itrace_entry(dp);
-
-       error = xfs_dir_lookup(NULL, dp, name, inum);
-       if (!error) {
-               /*
-                * Unlock the directory. We do this because we can't
-                * hold the directory lock while doing the vn_get()
-                * in xfs_iget().  Doing so could cause us to hold
-                * a lock while waiting for the inode to finish
-                * being inactive while it's waiting for a log
-                * reservation in the inactive routine.
-                */
-               xfs_iunlock(dp, lock_mode);
-               error = xfs_iget(dp->i_mount, NULL, *inum, 0, 0, ipp, 0);
-               xfs_ilock(dp, lock_mode);
-
-               if (error) {
-                       *ipp = NULL;
-               } else if ((*ipp)->i_d.di_mode == 0) {
-                       /*
-                        * The inode has been freed.  Something is
-                        * wrong so just get out of here.
-                        */
-                       xfs_iunlock(dp, lock_mode);
-                       xfs_iput_new(*ipp, 0);
-                       *ipp = NULL;
-                       xfs_ilock(dp, lock_mode);
-                       error = XFS_ERROR(ENOENT);
-               }
-       }
-       return error;
-}
-
 /*
  * Allocates a new inode from disk and return a pointer to the
  * incore copy. This routine will internally commit the current
@@ -310,7 +267,7 @@ xfs_bump_ino_vers2(
 {
        xfs_mount_t     *mp;
 
-       ASSERT(ismrlocked (&ip->i_lock, MR_UPDATE));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        ASSERT(ip->i_d.di_version == XFS_DINODE_VERSION_1);
 
        ip->i_d.di_version = XFS_DINODE_VERSION_2;
index 175b126d2cab76c5d06772bff9dd644b5738b505..f316cb85d8e234eb21b573a0a59ddfbccc21a922 100644 (file)
@@ -21,8 +21,6 @@
 #define IRELE(ip)      VN_RELE(XFS_ITOV(ip))
 #define IHOLD(ip)      VN_HOLD(XFS_ITOV(ip))
 
-extern int xfs_dir_lookup_int(xfs_inode_t *, uint, struct xfs_name *,
-                               xfs_ino_t *, xfs_inode_t **);
 extern int xfs_truncate_file(xfs_mount_t *, xfs_inode_t *);
 extern int xfs_dir_ialloc(xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t,
                                xfs_dev_t, cred_t *, prid_t, int,
index fc48158fe4797acae6de9c0c9152ce506c2f154e..30bacd8bb0e5b8a86251e3dbe03f9fe2c6f08ace 100644 (file)
@@ -186,6 +186,7 @@ xfs_cleanup(void)
        kmem_zone_destroy(xfs_efi_zone);
        kmem_zone_destroy(xfs_ifork_zone);
        kmem_zone_destroy(xfs_ili_zone);
+       kmem_zone_destroy(xfs_log_ticket_zone);
 }
 
 /*
index 6650601c64f7644f612fa2488bdfd78a0a79720d..70702a60b4bbd908669a6d6e46dfb864db1e8241 100644 (file)
@@ -75,132 +75,6 @@ xfs_open(
        return 0;
 }
 
-/*
- * xfs_getattr
- */
-int
-xfs_getattr(
-       xfs_inode_t     *ip,
-       bhv_vattr_t     *vap,
-       int             flags)
-{
-       bhv_vnode_t     *vp = XFS_ITOV(ip);
-       xfs_mount_t     *mp = ip->i_mount;
-
-       xfs_itrace_entry(ip);
-
-       if (XFS_FORCED_SHUTDOWN(mp))
-               return XFS_ERROR(EIO);
-
-       if (!(flags & ATTR_LAZY))
-               xfs_ilock(ip, XFS_ILOCK_SHARED);
-
-       vap->va_size = XFS_ISIZE(ip);
-       if (vap->va_mask == XFS_AT_SIZE)
-               goto all_done;
-
-       vap->va_nblocks =
-               XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks);
-       vap->va_nodeid = ip->i_ino;
-#if XFS_BIG_INUMS
-       vap->va_nodeid += mp->m_inoadd;
-#endif
-       vap->va_nlink = ip->i_d.di_nlink;
-
-       /*
-        * Quick exit for non-stat callers
-        */
-       if ((vap->va_mask &
-           ~(XFS_AT_SIZE|XFS_AT_FSID|XFS_AT_NODEID|
-             XFS_AT_NLINK|XFS_AT_BLKSIZE)) == 0)
-               goto all_done;
-
-       /*
-        * Copy from in-core inode.
-        */
-       vap->va_mode = ip->i_d.di_mode;
-       vap->va_uid = ip->i_d.di_uid;
-       vap->va_gid = ip->i_d.di_gid;
-       vap->va_projid = ip->i_d.di_projid;
-
-       /*
-        * Check vnode type block/char vs. everything else.
-        */
-       switch (ip->i_d.di_mode & S_IFMT) {
-       case S_IFBLK:
-       case S_IFCHR:
-               vap->va_rdev = ip->i_df.if_u2.if_rdev;
-               vap->va_blocksize = BLKDEV_IOSIZE;
-               break;
-       default:
-               vap->va_rdev = 0;
-
-               if (!(XFS_IS_REALTIME_INODE(ip))) {
-                       vap->va_blocksize = xfs_preferred_iosize(mp);
-               } else {
-
-                       /*
-                        * If the file blocks are being allocated from a
-                        * realtime partition, then return the inode's
-                        * realtime extent size or the realtime volume's
-                        * extent size.
-                        */
-                       vap->va_blocksize =
-                               xfs_get_extsz_hint(ip) << mp->m_sb.sb_blocklog;
-               }
-               break;
-       }
-
-       vn_atime_to_timespec(vp, &vap->va_atime);
-       vap->va_mtime.tv_sec = ip->i_d.di_mtime.t_sec;
-       vap->va_mtime.tv_nsec = ip->i_d.di_mtime.t_nsec;
-       vap->va_ctime.tv_sec = ip->i_d.di_ctime.t_sec;
-       vap->va_ctime.tv_nsec = ip->i_d.di_ctime.t_nsec;
-
-       /*
-        * Exit for stat callers.  See if any of the rest of the fields
-        * to be filled in are needed.
-        */
-       if ((vap->va_mask &
-            (XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|
-             XFS_AT_GENCOUNT|XFS_AT_VCODE)) == 0)
-               goto all_done;
-
-       /*
-        * Convert di_flags to xflags.
-        */
-       vap->va_xflags = xfs_ip2xflags(ip);
-
-       /*
-        * Exit for inode revalidate.  See if any of the rest of
-        * the fields to be filled in are needed.
-        */
-       if ((vap->va_mask &
-            (XFS_AT_EXTSIZE|XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|
-             XFS_AT_GENCOUNT|XFS_AT_VCODE)) == 0)
-               goto all_done;
-
-       vap->va_extsize = ip->i_d.di_extsize << mp->m_sb.sb_blocklog;
-       vap->va_nextents =
-               (ip->i_df.if_flags & XFS_IFEXTENTS) ?
-                       ip->i_df.if_bytes / sizeof(xfs_bmbt_rec_t) :
-                       ip->i_d.di_nextents;
-       if (ip->i_afp)
-               vap->va_anextents =
-                       (ip->i_afp->if_flags & XFS_IFEXTENTS) ?
-                               ip->i_afp->if_bytes / sizeof(xfs_bmbt_rec_t) :
-                                ip->i_d.di_anextents;
-       else
-               vap->va_anextents = 0;
-       vap->va_gen = ip->i_d.di_gen;
-
- all_done:
-       if (!(flags & ATTR_LAZY))
-               xfs_iunlock(ip, XFS_ILOCK_SHARED);
-       return 0;
-}
-
-
 /*
  * xfs_setattr
  */
@@ -211,7 +85,6 @@ xfs_setattr(
        int                     flags,
        cred_t                  *credp)
 {
-       bhv_vnode_t             *vp = XFS_ITOV(ip);
        xfs_mount_t             *mp = ip->i_mount;
        xfs_trans_t             *tp;
        int                     mask;
@@ -222,7 +95,6 @@ xfs_setattr(
        gid_t                   gid=0, igid=0;
        int                     timeflags = 0;
        xfs_prid_t              projid=0, iprojid=0;
-       int                     mandlock_before, mandlock_after;
        struct xfs_dquot        *udqp, *gdqp, *olddquot1, *olddquot2;
        int                     file_owner;
        int                     need_iolock = 1;
@@ -383,7 +255,7 @@ xfs_setattr(
                                m |= S_ISGID;
 #if 0
                        /* Linux allows this, Irix doesn't. */
-                       if ((vap->va_mode & S_ISVTX) && !VN_ISDIR(vp))
+                       if ((vap->va_mode & S_ISVTX) && !S_ISDIR(ip->i_d.di_mode))
                                m |= S_ISVTX;
 #endif
                        if (m && !capable(CAP_FSETID))
@@ -461,10 +333,10 @@ xfs_setattr(
                        goto error_return;
                }
 
-               if (VN_ISDIR(vp)) {
+               if (S_ISDIR(ip->i_d.di_mode)) {
                        code = XFS_ERROR(EISDIR);
                        goto error_return;
-               } else if (!VN_ISREG(vp)) {
+               } else if (!S_ISREG(ip->i_d.di_mode)) {
                        code = XFS_ERROR(EINVAL);
                        goto error_return;
                }
@@ -626,9 +498,6 @@ xfs_setattr(
                xfs_trans_ihold(tp, ip);
        }
 
-       /* determine whether mandatory locking mode changes */
-       mandlock_before = MANDLOCK(vp, ip->i_d.di_mode);
-
        /*
         * Truncate file.  Must have write permission and not be a directory.
         */
@@ -858,13 +727,6 @@ xfs_setattr(
                code = xfs_trans_commit(tp, commit_flags);
        }
 
-       /*
-        * If the (regular) file's mandatory locking mode changed, then
-        * notify the vnode.  We do this under the inode lock to prevent
-        * racing calls to vop_vnode_change.
-        */
-       mandlock_after = MANDLOCK(vp, ip->i_d.di_mode);
-
        xfs_iunlock(ip, lock_flags);
 
        /*
@@ -1443,7 +1305,7 @@ xfs_inactive_attrs(
        int             error;
        xfs_mount_t     *mp;
 
-       ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE));
+       ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
        tp = *tpp;
        mp = ip->i_mount;
        ASSERT(ip->i_d.di_forkoff != 0);
@@ -1491,7 +1353,7 @@ xfs_release(
        xfs_mount_t     *mp = ip->i_mount;
        int             error;
 
-       if (!VN_ISREG(vp) || (ip->i_d.di_mode == 0))
+       if (!S_ISREG(ip->i_d.di_mode) || (ip->i_d.di_mode == 0))
                return 0;
 
        /* If this is a read-only mount, don't do this (would generate I/O) */
@@ -1774,8 +1636,7 @@ xfs_lookup(
        struct xfs_name         *name,
        xfs_inode_t             **ipp)
 {
-       xfs_inode_t             *ip;
-       xfs_ino_t               e_inum;
+       xfs_ino_t               inum;
        int                     error;
        uint                    lock_mode;
 
@@ -1785,12 +1646,21 @@ xfs_lookup(
                return XFS_ERROR(EIO);
 
        lock_mode = xfs_ilock_map_shared(dp);
-       error = xfs_dir_lookup_int(dp, lock_mode, name, &e_inum, &ip);
-       if (!error) {
-               *ipp = ip;
-               xfs_itrace_ref(ip);
-       }
+       error = xfs_dir_lookup(NULL, dp, name, &inum);
        xfs_iunlock_map_shared(dp, lock_mode);
+
+       if (error)
+               goto out;
+
+       error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp, 0);
+       if (error)
+               goto out;
+
+       xfs_itrace_ref(*ipp);
+       return 0;
+
+ out:
+       *ipp = NULL;
        return error;
 }
 
@@ -1906,7 +1776,7 @@ xfs_create(
         * It is locked (and joined to the transaction).
         */
 
-       ASSERT(ismrlocked (&ip->i_lock, MR_UPDATE));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 
        /*
         * Now we join the directory inode to the transaction.  We do not do it
@@ -2112,7 +1982,7 @@ again:
 
                ips[0] = ip;
                ips[1] = dp;
-               xfs_lock_inodes(ips, 2, 0, XFS_ILOCK_EXCL);
+               xfs_lock_inodes(ips, 2, XFS_ILOCK_EXCL);
        }
        /* else  e_inum == dp->i_ino */
        /*     This can happen if we're asked to lock /x/..
@@ -2160,7 +2030,6 @@ void
 xfs_lock_inodes(
        xfs_inode_t     **ips,
        int             inodes,
-       int             first_locked,
        uint            lock_mode)
 {
        int             attempts = 0, i, j, try_lock;
@@ -2168,13 +2037,8 @@ xfs_lock_inodes(
 
        ASSERT(ips && (inodes >= 2)); /* we need at least two */
 
-       if (first_locked) {
-               try_lock = 1;
-               i = 1;
-       } else {
-               try_lock = 0;
-               i = 0;
-       }
+       try_lock = 0;
+       i = 0;
 
 again:
        for (; i < inodes; i++) {
@@ -2298,29 +2162,14 @@ xfs_remove(
                        return error;
        }
 
-       /*
-        * We need to get a reference to ip before we get our log
-        * reservation. The reason for this is that we cannot call
-        * xfs_iget for an inode for which we do not have a reference
-        * once we've acquired a log reservation. This is because the
-        * inode we are trying to get might be in xfs_inactive going
-        * for a log reservation. Since we'll have to wait for the
-        * inactive code to complete before returning from xfs_iget,
-        * we need to make sure that we don't have log space reserved
-        * when we call xfs_iget.  Instead we get an unlocked reference
-        * to the inode before getting our log reservation.
-        */
-       IHOLD(ip);
-
        xfs_itrace_entry(ip);
        xfs_itrace_ref(ip);
 
        error = XFS_QM_DQATTACH(mp, dp, 0);
-       if (!error && dp != ip)
+       if (!error)
                error = XFS_QM_DQATTACH(mp, ip, 0);
        if (error) {
                REMOVE_DEBUG_TRACE(__LINE__);
-               IRELE(ip);
                goto std_return;
        }
 
@@ -2347,7 +2196,6 @@ xfs_remove(
                ASSERT(error != ENOSPC);
                REMOVE_DEBUG_TRACE(__LINE__);
                xfs_trans_cancel(tp, 0);
-               IRELE(ip);
                return error;
        }
 
@@ -2355,7 +2203,6 @@ xfs_remove(
        if (error) {
                REMOVE_DEBUG_TRACE(__LINE__);
                xfs_trans_cancel(tp, cancel_flags);
-               IRELE(ip);
                goto std_return;
        }
 
@@ -2363,23 +2210,18 @@ xfs_remove(
         * At this point, we've gotten both the directory and the entry
         * inodes locked.
         */
+       IHOLD(ip);
        xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
-       if (dp != ip) {
-               /*
-                * Increment vnode ref count only in this case since
-                * there's an extra vnode reference in the case where
-                * dp == ip.
-                */
-               IHOLD(dp);
-               xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
-       }
+
+       IHOLD(dp);
+       xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
 
        /*
         * Entry must exist since we did a lookup in xfs_lock_dir_and_entry.
         */
        XFS_BMAP_INIT(&free_list, &first_block);
        error = xfs_dir_removename(tp, dp, name, ip->i_ino,
-                                       &first_block, &free_list, 0);
+                                       &first_block, &free_list, resblks);
        if (error) {
                ASSERT(error != ENOENT);
                REMOVE_DEBUG_TRACE(__LINE__);
@@ -2401,12 +2243,6 @@ xfs_remove(
         */
        link_zero = (ip)->i_d.di_nlink==0;
 
-       /*
-        * Take an extra ref on the inode so that it doesn't
-        * go to xfs_inactive() from within the commit.
-        */
-       IHOLD(ip);
-
        /*
         * If this is a synchronous mount, make sure that the
         * remove transaction goes to disk before returning to
@@ -2423,10 +2259,8 @@ xfs_remove(
        }
 
        error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
-       if (error) {
-               IRELE(ip);
+       if (error)
                goto std_return;
-       }
 
        /*
         * If we are using filestreams, kill the stream association.
@@ -2438,7 +2272,6 @@ xfs_remove(
                xfs_filestream_deassociate(ip);
 
        xfs_itrace_exit(ip);
-       IRELE(ip);
 
 /*     Fall through to std_return with error = 0 */
  std_return:
@@ -2467,8 +2300,6 @@ xfs_remove(
        cancel_flags |= XFS_TRANS_ABORT;
        xfs_trans_cancel(tp, cancel_flags);
 
-       IRELE(ip);
-
        goto std_return;
 }
 
@@ -2536,7 +2367,7 @@ xfs_link(
                ips[1] = sip;
        }
 
-       xfs_lock_inodes(ips, 2, 0, XFS_ILOCK_EXCL);
+       xfs_lock_inodes(ips, 2, XFS_ILOCK_EXCL);
 
        /*
         * Increment vnode ref counts since xfs_trans_commit &
@@ -2840,7 +2671,6 @@ xfs_rmdir(
        struct xfs_name         *name,
        xfs_inode_t             *cdp)
 {
-       bhv_vnode_t             *dir_vp = XFS_ITOV(dp);
        xfs_mount_t             *mp = dp->i_mount;
        xfs_trans_t             *tp;
        int                     error;
@@ -2865,28 +2695,13 @@ xfs_rmdir(
                        return XFS_ERROR(error);
        }
 
-       /*
-        * We need to get a reference to cdp before we get our log
-        * reservation.  The reason for this is that we cannot call
-        * xfs_iget for an inode for which we do not have a reference
-        * once we've acquired a log reservation.  This is because the
-        * inode we are trying to get might be in xfs_inactive going
-        * for a log reservation.  Since we'll have to wait for the
-        * inactive code to complete before returning from xfs_iget,
-        * we need to make sure that we don't have log space reserved
-        * when we call xfs_iget.  Instead we get an unlocked reference
-        * to the inode before getting our log reservation.
-        */
-       IHOLD(cdp);
-
        /*
         * Get the dquots for the inodes.
         */
        error = XFS_QM_DQATTACH(mp, dp, 0);
-       if (!error && dp != cdp)
+       if (!error)
                error = XFS_QM_DQATTACH(mp, cdp, 0);
        if (error) {
-               IRELE(cdp);
                REMOVE_DEBUG_TRACE(__LINE__);
                goto std_return;
        }
@@ -2913,7 +2728,6 @@ xfs_rmdir(
        if (error) {
                ASSERT(error != ENOSPC);
                cancel_flags = 0;
-               IRELE(cdp);
                goto error_return;
        }
        XFS_BMAP_INIT(&free_list, &first_block);
@@ -2927,21 +2741,13 @@ xfs_rmdir(
        error = xfs_lock_dir_and_entry(dp, cdp);
        if (error) {
                xfs_trans_cancel(tp, cancel_flags);
-               IRELE(cdp);
                goto std_return;
        }
 
+       IHOLD(dp);
        xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
-       if (dp != cdp) {
-               /*
-                * Only increment the parent directory vnode count if
-                * we didn't bump it in looking up cdp.  The only time
-                * we don't bump it is when we're looking up ".".
-                */
-               VN_HOLD(dir_vp);
-       }
 
-       xfs_itrace_ref(cdp);
+       IHOLD(cdp);
        xfs_trans_ijoin(tp, cdp, XFS_ILOCK_EXCL);
 
        ASSERT(cdp->i_d.di_nlink >= 2);
@@ -2994,12 +2800,6 @@ xfs_rmdir(
        /* Determine these before committing transaction */
        last_cdp_link = (cdp)->i_d.di_nlink==0;
 
-       /*
-        * Take an extra ref on the child vnode so that it
-        * does not go to xfs_inactive() from within the commit.
-        */
-       IHOLD(cdp);
-
        /*
         * If this is a synchronous mount, make sure that the
         * rmdir transaction goes to disk before returning to
@@ -3014,19 +2814,15 @@ xfs_rmdir(
                xfs_bmap_cancel(&free_list);
                xfs_trans_cancel(tp, (XFS_TRANS_RELEASE_LOG_RES |
                                 XFS_TRANS_ABORT));
-               IRELE(cdp);
                goto std_return;
        }
 
        error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
        if (error) {
-               IRELE(cdp);
                goto std_return;
        }
 
 
-       IRELE(cdp);
-
        /* Fall through to std_return with error = 0 or the errno
         * from xfs_trans_commit. */
  std_return:
index 24c53923dc2c25b17f326bc03f1aae5f6ff2ed3a..8abe8f186e2019fbebcb5debcb26940ebe0ee077 100644 (file)
@@ -15,7 +15,6 @@ struct xfs_iomap;
 
 
 int xfs_open(struct xfs_inode *ip);
-int xfs_getattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags);
 int xfs_setattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags,
                struct cred *credp);
 int xfs_readlink(struct xfs_inode *ip, char *link);
@@ -48,9 +47,9 @@ int xfs_change_file_space(struct xfs_inode *ip, int cmd,
                struct cred *credp, int attr_flags);
 int xfs_rename(struct xfs_inode *src_dp, struct xfs_name *src_name,
                struct xfs_inode *src_ip, struct xfs_inode *target_dp,
-               struct xfs_name *target_name);
+               struct xfs_name *target_name, struct xfs_inode *target_ip);
 int xfs_attr_get(struct xfs_inode *ip, const char *name, char *value,
-               int *valuelenp, int flags, cred_t *cred);
+               int *valuelenp, int flags);
 int xfs_attr_set(struct xfs_inode *dp, const char *name, char *value,
                int valuelen, int flags);
 int xfs_attr_remove(struct xfs_inode *dp, const char *name, int flags);
@@ -61,9 +60,6 @@ int xfs_ioctl(struct xfs_inode *ip, struct file *filp,
 ssize_t xfs_read(struct xfs_inode *ip, struct kiocb *iocb,
                const struct iovec *iovp, unsigned int segs,
                loff_t *offset, int ioflags);
-ssize_t xfs_sendfile(struct xfs_inode *ip, struct file *filp,
-               loff_t *offset, int ioflags, size_t count,
-               read_actor_t actor, void *target);
 ssize_t xfs_splice_read(struct xfs_inode *ip, struct file *infilp,
                loff_t *ppos, struct pipe_inode_info *pipe, size_t count,
                int flags, int ioflags);
index a1d72846f61ca250b53d634404703af06149eb73..3787c60aed3fa716f366b7cf9868e4bcbef63eea 100644 (file)
@@ -1,6 +1,11 @@
-#ifndef __ALPHA_UNALIGNED_H
-#define __ALPHA_UNALIGNED_H
+#ifndef _ASM_ALPHA_UNALIGNED_H
+#define _ASM_ALPHA_UNALIGNED_H
 
-#include <asm-generic/unaligned.h>
+#include <linux/unaligned/le_struct.h>
+#include <linux/unaligned/be_byteshift.h>
+#include <linux/unaligned/generic.h>
 
-#endif
+#define get_unaligned __get_unaligned_le
+#define put_unaligned __put_unaligned_le
+
+#endif /* _ASM_ALPHA_UNALIGNED_H */
index 5148ab7ad1f83404b9ae53caeba8582f4ed08941..50f8c880220667cd4523ad1f5f061eb592c6908c 100644 (file)
@@ -20,11 +20,10 @@ static inline void __iomem *
 __arch_ioremap(unsigned long paddr, size_t size, unsigned int mtype)
 {
        void __iomem *retval;
-
-       if (mtype == MT_DEVICE && size && paddr >= ORION5X_REGS_PHYS_BASE &&
-           paddr + size <= ORION5X_REGS_PHYS_BASE + ORION5X_REGS_SIZE) {
-               retval = (void __iomem *)ORION5X_REGS_VIRT_BASE +
-                               (paddr - ORION5X_REGS_PHYS_BASE);
+       unsigned long offs = paddr - ORION5X_REGS_PHYS_BASE;
+       if (mtype == MT_DEVICE && size && offs < ORION5X_REGS_SIZE &&
+           size <= ORION5X_REGS_SIZE && offs + size <= ORION5X_REGS_SIZE) {
+               retval = (void __iomem *)ORION5X_REGS_VIRT_BASE + offs;
        } else {
                retval = __arm_ioremap(paddr, size, mtype);
        }
index 50c77eacbd5e435526ff36d1a5027181cfe19672..b6c8fe37768315bcc5081490572e2493e15910cf 100644 (file)
 /* ITE8152 irqs */
 /* add IT8152 IRQs beyond BOARD_END */
 #ifdef CONFIG_PCI_HOST_ITE8152
-#define IT8152_IRQ(x)   (IRQ_GPIO(IRQ_BOARD_END) + 1 + (x))
+#define IT8152_IRQ(x)   (IRQ_BOARD_END + (x))
 
 /* IRQ-sources in 3 groups - local devices, LPC (serial), and external PCI */
 #define IT8152_LD_IRQ_COUNT     9
 
 #define IT8152_LAST_IRQ         IT8152_LD_IRQ(IT8152_LD_IRQ_COUNT - 1)
 
+#if NR_IRQS < (IT8152_LAST_IRQ+1)
 #undef NR_IRQS
 #define NR_IRQS (IT8152_LAST_IRQ+1)
 #endif
+
+#endif /* CONFIG_PCI_HOST_ITE8152 */
index b34fd5683e2d20876805e6b7abe25a8708babced..169b374f9921968031b0b7dccb22673e3366256a 100644 (file)
@@ -13,7 +13,6 @@
 #define _MAGICIAN_H_
 
 #include <asm/arch/irqs.h>
-#include <asm/arch/pxa2xx-gpio.h>
 
 /*
  * PXA GPIOs
 #define GPIO119_MAGICIAN_UNKNOWN               119
 #define GPIO120_MAGICIAN_UNKNOWN               120
 
-/*
- * PXA GPIO alternate function mode & direction
- */
-
-#define GPIO0_MAGICIAN_KEY_POWER_MD            (0 | GPIO_IN)
-#define GPIO9_MAGICIAN_UNKNOWN_MD              (9 | GPIO_IN)
-#define GPIO10_MAGICIAN_GSM_IRQ_MD             (10 | GPIO_IN)
-#define GPIO11_MAGICIAN_GSM_OUT1_MD            (11 | GPIO_OUT)
-#define GPIO13_MAGICIAN_CPLD_IRQ_MD            (13 | GPIO_IN)
-#define GPIO18_MAGICIAN_UNKNOWN_MD             (18 | GPIO_OUT)
-#define GPIO22_MAGICIAN_VIBRA_EN_MD            (22 | GPIO_OUT)
-#define GPIO26_MAGICIAN_GSM_POWER_MD           (26 | GPIO_OUT)
-#define GPIO27_MAGICIAN_USBC_PUEN_MD           (27 | GPIO_OUT)
-#define GPIO30_MAGICIAN_nCHARGE_EN_MD          (30 | GPIO_OUT)
-#define GPIO37_MAGICIAN_KEY_HANGUP_MD          (37 | GPIO_OUT)
-#define GPIO38_MAGICIAN_KEY_CONTACTS_MD                (38 | GPIO_OUT)
-#define GPIO40_MAGICIAN_GSM_OUT2_MD            (40 | GPIO_OUT)
-#define GPIO48_MAGICIAN_UNKNOWN_MD             (48 | GPIO_OUT)
-#define GPIO56_MAGICIAN_UNKNOWN_MD             (56 | GPIO_OUT)
-#define GPIO57_MAGICIAN_CAM_RESET_MD           (57 | GPIO_OUT)
-#define GPIO75_MAGICIAN_SAMSUNG_POWER_MD       (75 | GPIO_OUT)
-#define GPIO83_MAGICIAN_nIR_EN_MD              (83 | GPIO_OUT)
-#define GPIO86_MAGICIAN_GSM_RESET_MD           (86 | GPIO_OUT)
-#define GPIO87_MAGICIAN_GSM_SELECT_MD          (87 | GPIO_OUT)
-#define GPIO90_MAGICIAN_KEY_CALENDAR_MD                (90 | GPIO_OUT)
-#define GPIO91_MAGICIAN_KEY_CAMERA_MD          (91 | GPIO_OUT)
-#define GPIO93_MAGICIAN_KEY_UP_MD              (93 | GPIO_IN)
-#define GPIO94_MAGICIAN_KEY_DOWN_MD            (94 | GPIO_IN)
-#define GPIO95_MAGICIAN_KEY_LEFT_MD            (95 | GPIO_IN)
-#define GPIO96_MAGICIAN_KEY_RIGHT_MD           (96 | GPIO_IN)
-#define GPIO97_MAGICIAN_KEY_ENTER_MD           (97 | GPIO_IN)
-#define GPIO98_MAGICIAN_KEY_RECORD_MD          (98 | GPIO_IN)
-#define GPIO99_MAGICIAN_HEADPHONE_IN_MD                (99 | GPIO_IN)
-#define GPIO100_MAGICIAN_KEY_VOL_UP_MD         (100 | GPIO_IN)
-#define GPIO101_MAGICIAN_KEY_VOL_DOWN_MD       (101 | GPIO_IN)
-#define GPIO102_MAGICIAN_KEY_PHONE_MD          (102 | GPIO_IN)
-#define GPIO103_MAGICIAN_LED_KP_MD             (103 | GPIO_OUT)
-#define GPIO104_MAGICIAN_LCD_POWER_1_MD        (104 | GPIO_OUT)
-#define GPIO105_MAGICIAN_LCD_POWER_2_MD                (105 | GPIO_OUT)
-#define GPIO106_MAGICIAN_LCD_POWER_3_MD                (106 | GPIO_OUT)
-#define GPIO107_MAGICIAN_DS1WM_IRQ_MD          (107 | GPIO_IN)
-#define GPIO108_MAGICIAN_GSM_READY_MD          (108 | GPIO_IN)
-#define GPIO114_MAGICIAN_UNKNOWN_MD            (114 | GPIO_OUT)
-#define GPIO115_MAGICIAN_nPEN_IRQ_MD           (115 | GPIO_IN)
-#define GPIO116_MAGICIAN_nCAM_EN_MD            (116 | GPIO_OUT)
-#define GPIO119_MAGICIAN_UNKNOWN_MD            (119 | GPIO_OUT)
-#define GPIO120_MAGICIAN_UNKNOWN_MD            (120 | GPIO_OUT)
-
 /*
  * CPLD IRQs
  */
index a322012f16acf55f66dd28fb3870fcb7bfed5505..4b2ea1e95c5799b2f1db6effcf557760fd899b69 100644 (file)
 #define OSCC_OON       (1 << 1)        /* 32.768kHz OON (write-once only bit) */
 #define OSCC_OOK       (1 << 0)        /* 32.768kHz OOK (read-only bit) */
 
-
-/*
- * LCD
- */
-
-#define LCCR0          __REG(0x44000000)  /* LCD Controller Control Register 0 */
-#define LCCR1          __REG(0x44000004)  /* LCD Controller Control Register 1 */
-#define LCCR2          __REG(0x44000008)  /* LCD Controller Control Register 2 */
-#define LCCR3          __REG(0x4400000C)  /* LCD Controller Control Register 3 */
-#define LCCR4          __REG(0x44000010)  /* LCD Controller Control Register 3 */
-#define DFBR0          __REG(0x44000020)  /* DMA Channel 0 Frame Branch Register */
-#define DFBR1          __REG(0x44000024)  /* DMA Channel 1 Frame Branch Register */
-#define LCSR           __REG(0x44000038)  /* LCD Controller Status Register */
-#define LIIDR          __REG(0x4400003C)  /* LCD Controller Interrupt ID Register */
-#define TMEDRGBR       __REG(0x44000040)  /* TMED RGB Seed Register */
-#define TMEDCR         __REG(0x44000044)  /* TMED Control Register */
-
-#define LCCR3_1BPP (0 << 24)
-#define LCCR3_2BPP (1 << 24)
-#define LCCR3_4BPP (2 << 24)
-#define LCCR3_8BPP (3 << 24)
-#define LCCR3_16BPP (4 << 24)
-
-#define LCCR3_PDFOR_0 (0 << 30)
-#define LCCR3_PDFOR_1 (1 << 30)
-#define LCCR3_PDFOR_2 (2 << 30)
-#define LCCR3_PDFOR_3 (3 << 30)
-
-#define LCCR4_PAL_FOR_0 (0 << 15)
-#define LCCR4_PAL_FOR_1 (1 << 15)
-#define LCCR4_PAL_FOR_2 (2 << 15)
-#define LCCR4_PAL_FOR_MASK (3 << 15)
-
-#define FDADR0         __REG(0x44000200)  /* DMA Channel 0 Frame Descriptor Address Register */
-#define FSADR0         __REG(0x44000204)  /* DMA Channel 0 Frame Source Address Register */
-#define FIDR0          __REG(0x44000208)  /* DMA Channel 0 Frame ID Register */
-#define LDCMD0         __REG(0x4400020C)  /* DMA Channel 0 Command Register */
-#define FDADR1         __REG(0x44000210)  /* DMA Channel 1 Frame Descriptor Address Register */
-#define FSADR1         __REG(0x44000214)  /* DMA Channel 1 Frame Source Address Register */
-#define FIDR1          __REG(0x44000218)  /* DMA Channel 1 Frame ID Register */
-#define LDCMD1         __REG(0x4400021C)  /* DMA Channel 1 Command Register */
-
-#define LCCR0_ENB      (1 << 0)        /* LCD Controller enable */
-#define LCCR0_CMS      (1 << 1)        /* Color/Monochrome Display Select */
-#define LCCR0_Color     (LCCR0_CMS*0)   /*  Color display                  */
-#define LCCR0_Mono      (LCCR0_CMS*1)   /*  Monochrome display             */
-#define LCCR0_SDS      (1 << 2)        /* Single/Dual Panel Display       */
-                                        /* Select                          */
-#define LCCR0_Sngl      (LCCR0_SDS*0)   /*  Single panel display           */
-#define LCCR0_Dual      (LCCR0_SDS*1)   /*  Dual panel display             */
-
-#define LCCR0_LDM      (1 << 3)        /* LCD Disable Done Mask */
-#define LCCR0_SFM      (1 << 4)        /* Start of frame mask */
-#define LCCR0_IUM      (1 << 5)        /* Input FIFO underrun mask */
-#define LCCR0_EFM      (1 << 6)        /* End of Frame mask */
-#define LCCR0_PAS      (1 << 7)        /* Passive/Active display Select   */
-#define LCCR0_Pas       (LCCR0_PAS*0)   /*  Passive display (STN)          */
-#define LCCR0_Act       (LCCR0_PAS*1)   /*  Active display (TFT)           */
-#define LCCR0_DPD      (1 << 9)        /* Double Pixel Data (monochrome   */
-                                        /* display mode)                   */
-#define LCCR0_4PixMono  (LCCR0_DPD*0)   /*  4-Pixel/clock Monochrome       */
-                                        /*  display                        */
-#define LCCR0_8PixMono  (LCCR0_DPD*1)   /*  8-Pixel/clock Monochrome       */
-                                        /*  display                        */
-#define LCCR0_DIS      (1 << 10)       /* LCD Disable */
-#define LCCR0_QDM      (1 << 11)       /* LCD Quick Disable mask */
-#define LCCR0_PDD      (0xff << 12)    /* Palette DMA request delay */
-#define LCCR0_PDD_S    12
-#define LCCR0_BM       (1 << 20)       /* Branch mask */
-#define LCCR0_OUM      (1 << 21)       /* Output FIFO underrun mask */
-#define LCCR0_LCDT      (1 << 22)       /* LCD panel type */
-#define LCCR0_RDSTM     (1 << 23)       /* Read status interrupt mask */
-#define LCCR0_CMDIM     (1 << 24)       /* Command interrupt mask */
-#define LCCR0_OUC       (1 << 25)       /* Overlay Underlay control bit */
-#define LCCR0_LDDALT    (1 << 26)       /* LDD alternate mapping control */
-
-#define LCCR1_PPL       Fld (10, 0)      /* Pixels Per Line - 1 */
-#define LCCR1_DisWdth(Pixel)            /* Display Width [1..800 pix.]  */ \
-                        (((Pixel) - 1) << FShft (LCCR1_PPL))
-
-#define LCCR1_HSW       Fld (6, 10)     /* Horizontal Synchronization     */
-#define LCCR1_HorSnchWdth(Tpix)         /* Horizontal Synchronization     */ \
-                                        /* pulse Width [1..64 Tpix]       */ \
-                        (((Tpix) - 1) << FShft (LCCR1_HSW))
-
-#define LCCR1_ELW       Fld (8, 16)     /* End-of-Line pixel clock Wait    */
-                                        /* count - 1 [Tpix]                */
-#define LCCR1_EndLnDel(Tpix)            /*  End-of-Line Delay              */ \
-                                        /*  [1..256 Tpix]                  */ \
-                        (((Tpix) - 1) << FShft (LCCR1_ELW))
-
-#define LCCR1_BLW       Fld (8, 24)     /* Beginning-of-Line pixel clock   */
-                                        /* Wait count - 1 [Tpix]           */
-#define LCCR1_BegLnDel(Tpix)            /*  Beginning-of-Line Delay        */ \
-                                        /*  [1..256 Tpix]                  */ \
-                        (((Tpix) - 1) << FShft (LCCR1_BLW))
-
-
-#define LCCR2_LPP       Fld (10, 0)     /* Line Per Panel - 1              */
-#define LCCR2_DisHght(Line)             /*  Display Height [1..1024 lines] */ \
-                        (((Line) - 1) << FShft (LCCR2_LPP))
-
-#define LCCR2_VSW       Fld (6, 10)     /* Vertical Synchronization pulse  */
-                                        /* Width - 1 [Tln] (L_FCLK)        */
-#define LCCR2_VrtSnchWdth(Tln)          /*  Vertical Synchronization pulse */ \
-                                        /*  Width [1..64 Tln]              */ \
-                        (((Tln) - 1) << FShft (LCCR2_VSW))
-
-#define LCCR2_EFW       Fld (8, 16)     /* End-of-Frame line clock Wait    */
-                                        /* count [Tln]                     */
-#define LCCR2_EndFrmDel(Tln)            /*  End-of-Frame Delay             */ \
-                                        /*  [0..255 Tln]                   */ \
-                        ((Tln) << FShft (LCCR2_EFW))
-
-#define LCCR2_BFW       Fld (8, 24)     /* Beginning-of-Frame line clock   */
-                                        /* Wait count [Tln]                */
-#define LCCR2_BegFrmDel(Tln)            /*  Beginning-of-Frame Delay       */ \
-                                        /*  [0..255 Tln]                   */ \
-                        ((Tln) << FShft (LCCR2_BFW))
-
-#if 0
-#define LCCR3_PCD      (0xff)          /* Pixel clock divisor */
-#define LCCR3_ACB      (0xff << 8)     /* AC Bias pin frequency */
-#define LCCR3_ACB_S    8
-#endif
-
-#define LCCR3_API      (0xf << 16)     /* AC Bias pin trasitions per interrupt */
-#define LCCR3_API_S    16
-#define LCCR3_VSP      (1 << 20)       /* vertical sync polarity */
-#define LCCR3_HSP      (1 << 21)       /* horizontal sync polarity */
-#define LCCR3_PCP      (1 << 22)       /* Pixel Clock Polarity (L_PCLK)   */
-#define LCCR3_PixRsEdg  (LCCR3_PCP*0)   /*  Pixel clock Rising-Edge        */
-#define LCCR3_PixFlEdg  (LCCR3_PCP*1)   /*  Pixel clock Falling-Edge       */
-
-#define LCCR3_OEP       (1 << 23)       /* Output Enable Polarity (L_BIAS, */
-                                        /* active display mode)            */
-#define LCCR3_OutEnH    (LCCR3_OEP*0)   /*  Output Enable active High      */
-#define LCCR3_OutEnL    (LCCR3_OEP*1)   /*  Output Enable active Low       */
-
-#if 0
-#define LCCR3_BPP      (7 << 24)       /* bits per pixel */
-#define LCCR3_BPP_S    24
-#endif
-#define LCCR3_DPC      (1 << 27)       /* double pixel clock mode */
-
-
-#define LCCR3_PCD       Fld (8, 0)      /* Pixel Clock Divisor */
-#define LCCR3_PixClkDiv(Div)            /* Pixel Clock Divisor */ \
-                        (((Div) << FShft (LCCR3_PCD)))
-
-
-#define LCCR3_BPP       Fld (3, 24)     /* Bit Per Pixel */
-#define LCCR3_Bpp(Bpp)                  /* Bit Per Pixel */ \
-                        (((Bpp) << FShft (LCCR3_BPP)))
-
-#define LCCR3_ACB       Fld (8, 8)      /* AC Bias */
-#define LCCR3_Acb(Acb)                  /* BAC Bias */ \
-                        (((Acb) << FShft (LCCR3_ACB)))
-
-#define LCCR3_HorSnchH  (LCCR3_HSP*0)   /*  Horizontal Synchronization     */
-                                        /*  pulse active High              */
-#define LCCR3_HorSnchL  (LCCR3_HSP*1)   /*  Horizontal Synchronization     */
-
-#define LCCR3_VrtSnchH  (LCCR3_VSP*0)   /*  Vertical Synchronization pulse */
-                                        /*  active High                    */
-#define LCCR3_VrtSnchL  (LCCR3_VSP*1)   /*  Vertical Synchronization pulse */
-                                        /*  active Low                     */
-
-#define LCSR_LDD       (1 << 0)        /* LCD Disable Done */
-#define LCSR_SOF       (1 << 1)        /* Start of frame */
-#define LCSR_BER       (1 << 2)        /* Bus error */
-#define LCSR_ABC       (1 << 3)        /* AC Bias count */
-#define LCSR_IUL       (1 << 4)        /* input FIFO underrun Lower panel */
-#define LCSR_IUU       (1 << 5)        /* input FIFO underrun Upper panel */
-#define LCSR_OU                (1 << 6)        /* output FIFO underrun */
-#define LCSR_QD                (1 << 7)        /* quick disable */
-#define LCSR_EOF       (1 << 8)        /* end of frame */
-#define LCSR_BS                (1 << 9)        /* branch status */
-#define LCSR_SINT      (1 << 10)       /* subsequent interrupt */
-
-#define LDCMD_PAL      (1 << 26)       /* instructs DMA to load palette buffer */
-
-#define LCSR_LDD       (1 << 0)        /* LCD Disable Done */
-#define LCSR_SOF       (1 << 1)        /* Start of frame */
-#define LCSR_BER       (1 << 2)        /* Bus error */
-#define LCSR_ABC       (1 << 3)        /* AC Bias count */
-#define LCSR_IUL       (1 << 4)        /* input FIFO underrun Lower panel */
-#define LCSR_IUU       (1 << 5)        /* input FIFO underrun Upper panel */
-#define LCSR_OU                (1 << 6)        /* output FIFO underrun */
-#define LCSR_QD                (1 << 7)        /* quick disable */
-#define LCSR_EOF       (1 << 8)        /* end of frame */
-#define LCSR_BS                (1 << 9)        /* branch status */
-#define LCSR_SINT      (1 << 10)       /* subsequent interrupt */
-
-#define LDCMD_PAL      (1 << 26)       /* instructs DMA to load palette buffer */
-
 #ifdef CONFIG_PXA27x
 
 /* Camera Interface */
index ea2336aa70e47ea6fab3bce62a6d483424a02fbc..bbd22396841ae15d0eefcd235ffeccd9abdacb8b 100644 (file)
  */
 
 #include <linux/fb.h>
+#include <asm/arch/regs-lcd.h>
+
+/*
+ * Supported LCD connections
+ *
+ * bits 0 - 3: for LCD panel type:
+ *
+ *   STN  - for passive matrix
+ *   DSTN - for dual scan passive matrix
+ *   TFT  - for active matrix
+ *
+ * bits 4 - 9 : for bus width
+ * bits 10-17 : for AC Bias Pin Frequency
+ * bit     18 : for output enable polarity
+ * bit     19 : for pixel clock edge
+ */
+#define LCD_CONN_TYPE(_x)      ((_x) & 0x0f)
+#define LCD_CONN_WIDTH(_x)     (((_x) >> 4) & 0x1f)
+
+#define LCD_TYPE_UNKNOWN       0
+#define LCD_TYPE_MONO_STN      1
+#define LCD_TYPE_MONO_DSTN     2
+#define LCD_TYPE_COLOR_STN     3
+#define LCD_TYPE_COLOR_DSTN    4
+#define LCD_TYPE_COLOR_TFT     5
+#define LCD_TYPE_SMART_PANEL   6
+#define LCD_TYPE_MAX           7
+
+#define LCD_MONO_STN_4BPP      ((4  << 4) | LCD_TYPE_MONO_STN)
+#define LCD_MONO_STN_8BPP      ((8  << 4) | LCD_TYPE_MONO_STN)
+#define LCD_MONO_DSTN_8BPP     ((8  << 4) | LCD_TYPE_MONO_DSTN)
+#define LCD_COLOR_STN_8BPP     ((8  << 4) | LCD_TYPE_COLOR_STN)
+#define LCD_COLOR_DSTN_16BPP   ((16 << 4) | LCD_TYPE_COLOR_DSTN)
+#define LCD_COLOR_TFT_16BPP    ((16 << 4) | LCD_TYPE_COLOR_TFT)
+#define LCD_COLOR_TFT_18BPP    ((18 << 4) | LCD_TYPE_COLOR_TFT)
+#define LCD_SMART_PANEL_8BPP   ((8  << 4) | LCD_TYPE_SMART_PANEL)
+#define LCD_SMART_PANEL_16BPP  ((16 << 4) | LCD_TYPE_SMART_PANEL)
+#define LCD_SMART_PANEL_18BPP  ((18 << 4) | LCD_TYPE_SMART_PANEL)
+
+#define LCD_AC_BIAS_FREQ(x)    (((x) & 0xff) << 10)
+#define LCD_BIAS_ACTIVE_HIGH   (0 << 17)
+#define LCD_BIAS_ACTIVE_LOW    (1 << 17)
+#define LCD_PCLK_EDGE_RISE     (0 << 18)
+#define LCD_PCLK_EDGE_FALL     (1 << 18)
 
 /*
  * This structure describes the machine which we are running on.
@@ -26,6 +70,10 @@ struct pxafb_mode_info {
        u_short         yres;
 
        u_char          bpp;
+       u_int           cmap_greyscale:1,
+                       unused:31;
+
+       /* Parallel Mode Timing */
        u_char          hsync_len;
        u_char          left_margin;
        u_char          right_margin;
@@ -35,14 +83,28 @@ struct pxafb_mode_info {
        u_char          lower_margin;
        u_char          sync;
 
-       u_int           cmap_greyscale:1,
-                       unused:31;
+       /* Smart Panel Mode Timing - see PXA27x DM 7.4.15.0.3 for details
+        * Note:
+        * 1. all parameters in nanosecond (ns)
+        * 2. a0cs{rd,wr}_set_hld are controlled by the same register bits
+        *    in pxa27x and pxa3xx, initialize them to the same value or
+        *    the larger one will be used
+        * 3. same to {rd,wr}_pulse_width
+        */
+       unsigned        a0csrd_set_hld; /* A0 and CS Setup/Hold Time before/after L_FCLK_RD */
+       unsigned        a0cswr_set_hld; /* A0 and CS Setup/Hold Time before/after L_PCLK_WR */
+       unsigned        wr_pulse_width; /* L_PCLK_WR pulse width */
+       unsigned        rd_pulse_width; /* L_FCLK_RD pulse width */
+       unsigned        cmd_inh_time;   /* Command Inhibit time between two writes */
+       unsigned        op_hold_time;   /* Output Hold time from L_FCLK_RD negation */
 };
 
 struct pxafb_mach_info {
        struct pxafb_mode_info *modes;
        unsigned int num_modes;
 
+       unsigned int    lcd_conn;
+
        u_int           fixed_modes:1,
                        cmap_inverse:1,
                        cmap_static:1,
@@ -78,8 +140,11 @@ struct pxafb_mach_info {
        u_int           lccr4;
        void (*pxafb_backlight_power)(int);
        void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
-
+       void (*smart_update)(struct fb_info *);
 };
 void set_pxa_fb_info(struct pxafb_mach_info *hard_pxa_fb_info);
 void set_pxa_fb_parent(struct device *parent_dev);
 unsigned long pxafb_get_hsync_time(struct device *dev);
+
+extern int pxafb_smart_queue(struct fb_info *info, uint16_t *cmds, int);
+extern int pxafb_smart_flush(struct fb_info *info);
diff --git a/include/asm-arm/arch-pxa/regs-lcd.h b/include/asm-arm/arch-pxa/regs-lcd.h
new file mode 100644 (file)
index 0000000..f762493
--- /dev/null
@@ -0,0 +1,171 @@
+#ifndef __ASM_ARCH_REGS_LCD_H
+#define __ASM_ARCH_REGS_LCD_H
+/*
+ * LCD Controller Registers and Bits Definitions
+ */
+#define LCCR0          (0x000) /* LCD Controller Control Register 0 */
+#define LCCR1          (0x004) /* LCD Controller Control Register 1 */
+#define LCCR2          (0x008) /* LCD Controller Control Register 2 */
+#define LCCR3          (0x00C) /* LCD Controller Control Register 3 */
+#define LCCR4          (0x010) /* LCD Controller Control Register 4 */
+#define LCCR5          (0x014) /* LCD Controller Control Register 5 */
+#define DFBR0          (0x020) /* DMA Channel 0 Frame Branch Register */
+#define DFBR1          (0x024) /* DMA Channel 1 Frame Branch Register */
+#define LCSR           (0x038) /* LCD Controller Status Register */
+#define LIIDR          (0x03C) /* LCD Controller Interrupt ID Register */
+#define TMEDRGBR       (0x040) /* TMED RGB Seed Register */
+#define TMEDCR         (0x044) /* TMED Control Register */
+
+#define CMDCR          (0x100) /* Command Control Register */
+#define PRSR           (0x104) /* Panel Read Status Register */
+
+#define LCCR3_1BPP     (0 << 24)
+#define LCCR3_2BPP     (1 << 24)
+#define LCCR3_4BPP     (2 << 24)
+#define LCCR3_8BPP     (3 << 24)
+#define LCCR3_16BPP    (4 << 24)
+
+#define LCCR3_PDFOR_0  (0 << 30)
+#define LCCR3_PDFOR_1  (1 << 30)
+#define LCCR3_PDFOR_2  (2 << 30)
+#define LCCR3_PDFOR_3  (3 << 30)
+
+#define LCCR4_PAL_FOR_0        (0 << 15)
+#define LCCR4_PAL_FOR_1        (1 << 15)
+#define LCCR4_PAL_FOR_2        (2 << 15)
+#define LCCR4_PAL_FOR_MASK     (3 << 15)
+
+#define FDADR0         (0x200) /* DMA Channel 0 Frame Descriptor Address Register */
+#define FSADR0         (0x204) /* DMA Channel 0 Frame Source Address Register */
+#define FIDR0          (0x208) /* DMA Channel 0 Frame ID Register */
+#define LDCMD0         (0x20C) /* DMA Channel 0 Command Register */
+#define FDADR1         (0x210) /* DMA Channel 1 Frame Descriptor Address Register */
+#define FSADR1         (0x214) /* DMA Channel 1 Frame Source Address Register */
+#define FIDR1          (0x218) /* DMA Channel 1 Frame ID Register */
+#define LDCMD1         (0x21C) /* DMA Channel 1 Command Register */
+#define FDADR6         (0x260) /* DMA Channel 6 Frame Descriptor Address Register */
+#define FSADR6         (0x264) /* DMA Channel 6 Frame Source Address Register */
+#define FIDR6          (0x268) /* DMA Channel 6 Frame ID Register */
+
+#define LCCR0_ENB      (1 << 0)        /* LCD Controller enable */
+#define LCCR0_CMS      (1 << 1)        /* Color/Monochrome Display Select */
+#define LCCR0_Color    (LCCR0_CMS*0)   /*  Color display */
+#define LCCR0_Mono     (LCCR0_CMS*1)   /*  Monochrome display */
+#define LCCR0_SDS      (1 << 2)        /* Single/Dual Panel Display Select */
+#define LCCR0_Sngl     (LCCR0_SDS*0)   /*  Single panel display */
+#define LCCR0_Dual     (LCCR0_SDS*1)   /*  Dual panel display */
+
+#define LCCR0_LDM      (1 << 3)        /* LCD Disable Done Mask */
+#define LCCR0_SFM      (1 << 4)        /* Start of frame mask */
+#define LCCR0_IUM      (1 << 5)        /* Input FIFO underrun mask */
+#define LCCR0_EFM      (1 << 6)        /* End of Frame mask */
+#define LCCR0_PAS      (1 << 7)        /* Passive/Active display Select */
+#define LCCR0_Pas      (LCCR0_PAS*0)   /*  Passive display (STN) */
+#define LCCR0_Act      (LCCR0_PAS*1)   /*  Active display (TFT) */
+#define LCCR0_DPD      (1 << 9)        /* Double Pixel Data (monochrome) */
+#define LCCR0_4PixMono (LCCR0_DPD*0)   /*  4-Pixel/clock Monochrome display */
+#define LCCR0_8PixMono (LCCR0_DPD*1)   /*  8-Pixel/clock Monochrome display */
+#define LCCR0_DIS      (1 << 10)       /* LCD Disable */
+#define LCCR0_QDM      (1 << 11)       /* LCD Quick Disable mask */
+#define LCCR0_PDD      (0xff << 12)    /* Palette DMA request delay */
+#define LCCR0_PDD_S    12
+#define LCCR0_BM       (1 << 20)       /* Branch mask */
+#define LCCR0_OUM      (1 << 21)       /* Output FIFO underrun mask */
+#define LCCR0_LCDT     (1 << 22)       /* LCD panel type */
+#define LCCR0_RDSTM    (1 << 23)       /* Read status interrupt mask */
+#define LCCR0_CMDIM    (1 << 24)       /* Command interrupt mask */
+#define LCCR0_OUC      (1 << 25)       /* Overlay Underlay control bit */
+#define LCCR0_LDDALT   (1 << 26)       /* LDD alternate mapping control */
+
+#define LCCR1_PPL      Fld (10, 0)     /* Pixels Per Line - 1 */
+#define LCCR1_DisWdth(Pixel)   (((Pixel) - 1) << FShft (LCCR1_PPL))
+
+#define LCCR1_HSW      Fld (6, 10)     /* Horizontal Synchronization */
+#define LCCR1_HorSnchWdth(Tpix)        (((Tpix) - 1) << FShft (LCCR1_HSW))
+
+#define LCCR1_ELW      Fld (8, 16)     /* End-of-Line pixel clock Wait - 1 */
+#define LCCR1_EndLnDel(Tpix)   (((Tpix) - 1) << FShft (LCCR1_ELW))
+
+#define LCCR1_BLW      Fld (8, 24)     /* Beginning-of-Line pixel clock */
+#define LCCR1_BegLnDel(Tpix)   (((Tpix) - 1) << FShft (LCCR1_BLW))
+
+#define LCCR2_LPP      Fld (10, 0)     /* Line Per Panel - 1 */
+#define LCCR2_DisHght(Line)    (((Line) - 1) << FShft (LCCR2_LPP))
+
+#define LCCR2_VSW      Fld (6, 10)     /* Vertical Synchronization pulse - 1 */
+#define LCCR2_VrtSnchWdth(Tln) (((Tln) - 1) << FShft (LCCR2_VSW))
+
+#define LCCR2_EFW      Fld (8, 16)     /* End-of-Frame line clock Wait */
+#define LCCR2_EndFrmDel(Tln)   ((Tln) << FShft (LCCR2_EFW))
+
+#define LCCR2_BFW      Fld (8, 24)     /* Beginning-of-Frame line clock */
+#define LCCR2_BegFrmDel(Tln)   ((Tln) << FShft (LCCR2_BFW))
+
+#define LCCR3_API      (0xf << 16)     /* AC Bias pin trasitions per interrupt */
+#define LCCR3_API_S    16
+#define LCCR3_VSP      (1 << 20)       /* vertical sync polarity */
+#define LCCR3_HSP      (1 << 21)       /* horizontal sync polarity */
+#define LCCR3_PCP      (1 << 22)       /* Pixel Clock Polarity (L_PCLK) */
+#define LCCR3_PixRsEdg (LCCR3_PCP*0)   /*  Pixel clock Rising-Edge */
+#define LCCR3_PixFlEdg (LCCR3_PCP*1)   /*  Pixel clock Falling-Edge */
+
+#define LCCR3_OEP      (1 << 23)       /* Output Enable Polarity */
+#define LCCR3_OutEnH   (LCCR3_OEP*0)   /*  Output Enable active High */
+#define LCCR3_OutEnL   (LCCR3_OEP*1)   /*  Output Enable active Low */
+
+#define LCCR3_DPC      (1 << 27)       /* double pixel clock mode */
+#define LCCR3_PCD      Fld (8, 0)      /* Pixel Clock Divisor */
+#define LCCR3_PixClkDiv(Div)   (((Div) << FShft (LCCR3_PCD)))
+
+#define LCCR3_BPP      Fld (3, 24)     /* Bit Per Pixel */
+#define LCCR3_Bpp(Bpp) (((Bpp) << FShft (LCCR3_BPP)))
+
+#define LCCR3_ACB      Fld (8, 8)      /* AC Bias */
+#define LCCR3_Acb(Acb) (((Acb) << FShft (LCCR3_ACB)))
+
+#define LCCR3_HorSnchH (LCCR3_HSP*0)   /*  HSP Active High */
+#define LCCR3_HorSnchL (LCCR3_HSP*1)   /*  HSP Active Low */
+
+#define LCCR3_VrtSnchH (LCCR3_VSP*0)   /*  VSP Active High */
+#define LCCR3_VrtSnchL (LCCR3_VSP*1)   /*  VSP Active Low */
+
+#define LCCR5_IUM(x)   (1 << ((x) + 23)) /* input underrun mask */
+#define LCCR5_BSM(x)   (1 << ((x) + 15)) /* branch mask */
+#define LCCR5_EOFM(x)  (1 << ((x) + 7))  /* end of frame mask */
+#define LCCR5_SOFM(x)  (1 << ((x) + 0))  /* start of frame mask */
+
+#define LCSR_LDD       (1 << 0)        /* LCD Disable Done */
+#define LCSR_SOF       (1 << 1)        /* Start of frame */
+#define LCSR_BER       (1 << 2)        /* Bus error */
+#define LCSR_ABC       (1 << 3)        /* AC Bias count */
+#define LCSR_IUL       (1 << 4)        /* input FIFO underrun Lower panel */
+#define LCSR_IUU       (1 << 5)        /* input FIFO underrun Upper panel */
+#define LCSR_OU                (1 << 6)        /* output FIFO underrun */
+#define LCSR_QD                (1 << 7)        /* quick disable */
+#define LCSR_EOF       (1 << 8)        /* end of frame */
+#define LCSR_BS                (1 << 9)        /* branch status */
+#define LCSR_SINT      (1 << 10)       /* subsequent interrupt */
+#define LCSR_RD_ST     (1 << 11)       /* read status */
+#define LCSR_CMD_INT   (1 << 12)       /* command interrupt */
+
+#define LDCMD_PAL      (1 << 26)       /* instructs DMA to load palette buffer */
+
+/* smartpanel related */
+#define PRSR_DATA(x)   ((x) & 0xff)    /* Panel Data */
+#define PRSR_A0                (1 << 8)        /* Read Data Source */
+#define PRSR_ST_OK     (1 << 9)        /* Status OK */
+#define PRSR_CON_NT    (1 << 10)       /* Continue to Next Command */
+
+#define SMART_CMD_A0                    (0x1 << 8)
+#define SMART_CMD_READ_STATUS_REG       (0x0 << 9)
+#define SMART_CMD_READ_FRAME_BUFFER    ((0x0 << 9) | SMART_CMD_A0)
+#define SMART_CMD_WRITE_COMMAND                 (0x1 << 9)
+#define SMART_CMD_WRITE_DATA           ((0x1 << 9) | SMART_CMD_A0)
+#define SMART_CMD_WRITE_FRAME          ((0x2 << 9) | SMART_CMD_A0)
+#define SMART_CMD_WAIT_FOR_VSYNC        (0x3 << 9)
+#define SMART_CMD_NOOP                  (0x4 << 9)
+#define SMART_CMD_INTERRUPT             (0x5 << 9)
+
+#define SMART_CMD(x)   (SMART_CMD_WRITE_COMMAND | ((x) & 0xff))
+#define SMART_DAT(x)   (SMART_CMD_WRITE_DATA | ((x) & 0xff))
+#endif /* __ASM_ARCH_REGS_LCD_H */
index 1d56a3ef89fd3844df65403921f6a6b6c6ad45ab..a758a719180f64e5f4167eea0e9b6ca8b6ff3a75 100644 (file)
@@ -22,6 +22,8 @@ static inline void arch_idle(void)
 
 static inline void arch_reset(char mode)
 {
+       RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
+
        if (mode == 's') {
                /* Jump into ROM at address 0 */
                cpu_reset(0);
index c86f68ee65118b6c7cdd2fec34ee7509abbaae46..5c22b01121069751e2ed73049ec6d37ae54a18c9 100644 (file)
 # endif
 #endif
 
+#ifdef CONFIG_CPU_COPY_FEROCEON
+# ifdef _USER
+#  define MULTI_USER 1
+# else
+#  define _USER feroceon
+# endif
+#endif
+
 #ifdef CONFIG_CPU_SA1100
 # ifdef _USER
 #  define MULTI_USER 1
index 5db03cf3b90525d2164175288bd0f5a28f3efe7a..44593a8949038d18f566a821b6c0d99161de43a5 100644 (file)
@@ -1,171 +1,9 @@
-#ifndef __ASM_ARM_UNALIGNED_H
-#define __ASM_ARM_UNALIGNED_H
+#ifndef _ASM_ARM_UNALIGNED_H
+#define _ASM_ARM_UNALIGNED_H
 
-#include <asm/types.h>
-
-extern int __bug_unaligned_x(const void *ptr);
-
-/*
- * What is the most efficient way of loading/storing an unaligned value?
- *
- * That is the subject of this file.  Efficiency here is defined as
- * minimum code size with minimum register usage for the common cases.
- * It is currently not believed that long longs are common, so we
- * trade efficiency for the chars, shorts and longs against the long
- * longs.
- *
- * Current stats with gcc 2.7.2.2 for these functions:
- *
- *     ptrsize get:    code    regs    put:    code    regs
- *     1               1       1               1       2
- *     2               3       2               3       2
- *     4               7       3               7       3
- *     8               20      6               16      6
- *
- * gcc 2.95.1 seems to code differently:
- *
- *     ptrsize get:    code    regs    put:    code    regs
- *     1               1       1               1       2
- *     2               3       2               3       2
- *     4               7       4               7       4
- *     8               19      8               15      6
- *
- * which may or may not be more efficient (depending upon whether
- * you can afford the extra registers).  Hopefully the gcc 2.95
- * is inteligent enough to decide if it is better to use the
- * extra register, but evidence so far seems to suggest otherwise.
- *
- * Unfortunately, gcc is not able to optimise the high word
- * out of long long >> 32, or the low word from long long << 32
- */
-
-#define __get_unaligned_2_le(__p)                                      \
-       (unsigned int)(__p[0] | __p[1] << 8)
-
-#define __get_unaligned_2_be(__p)                                      \
-       (unsigned int)(__p[0] << 8 | __p[1])
-
-#define __get_unaligned_4_le(__p)                                      \
-       (unsigned int)(__p[0] | __p[1] << 8 | __p[2] << 16 | __p[3] << 24)
-
-#define __get_unaligned_4_be(__p)                                      \
-       (unsigned int)(__p[0] << 24 | __p[1] << 16 | __p[2] << 8 | __p[3])
-
-#define __get_unaligned_8_le(__p)                                      \
-       ((unsigned long long)__get_unaligned_4_le((__p+4)) << 32 |      \
-               __get_unaligned_4_le(__p))
-
-#define __get_unaligned_8_be(__p)                                      \
-       ((unsigned long long)__get_unaligned_4_be(__p) << 32 |          \
-               __get_unaligned_4_be((__p+4)))
-
-#define __get_unaligned_le(ptr)                                                \
-       ((__force typeof(*(ptr)))({                                     \
-               const __u8 *__p = (const __u8 *)(ptr);                  \
-               __builtin_choose_expr(sizeof(*(ptr)) == 1, *__p,        \
-                 __builtin_choose_expr(sizeof(*(ptr)) == 2, __get_unaligned_2_le(__p), \
-                 __builtin_choose_expr(sizeof(*(ptr)) == 4, __get_unaligned_4_le(__p), \
-                 __builtin_choose_expr(sizeof(*(ptr)) == 8, __get_unaligned_8_le(__p), \
-                   (void)__bug_unaligned_x(__p)))));                   \
-       }))
-
-#define __get_unaligned_be(ptr)                                                \
-       ((__force typeof(*(ptr)))({                                     \
-               const __u8 *__p = (const __u8 *)(ptr);                  \
-               __builtin_choose_expr(sizeof(*(ptr)) == 1, *__p,        \
-                 __builtin_choose_expr(sizeof(*(ptr)) == 2, __get_unaligned_2_be(__p), \
-                 __builtin_choose_expr(sizeof(*(ptr)) == 4, __get_unaligned_4_be(__p), \
-                 __builtin_choose_expr(sizeof(*(ptr)) == 8, __get_unaligned_8_be(__p), \
-                   (void)__bug_unaligned_x(__p)))));                   \
-       }))
-
-
-static inline void __put_unaligned_2_le(__u32 __v, register __u8 *__p)
-{
-       *__p++ = __v;
-       *__p++ = __v >> 8;
-}
-
-static inline void __put_unaligned_2_be(__u32 __v, register __u8 *__p)
-{
-       *__p++ = __v >> 8;
-       *__p++ = __v;
-}
-
-static inline void __put_unaligned_4_le(__u32 __v, register __u8 *__p)
-{
-       __put_unaligned_2_le(__v >> 16, __p + 2);
-       __put_unaligned_2_le(__v, __p);
-}
-
-static inline void __put_unaligned_4_be(__u32 __v, register __u8 *__p)
-{
-       __put_unaligned_2_be(__v >> 16, __p);
-       __put_unaligned_2_be(__v, __p + 2);
-}
-
-static inline void __put_unaligned_8_le(const unsigned long long __v, register __u8 *__p)
-{
-       /*
-        * tradeoff: 8 bytes of stack for all unaligned puts (2
-        * instructions), or an extra register in the long long
-        * case - go for the extra register.
-        */
-       __put_unaligned_4_le(__v >> 32, __p+4);
-       __put_unaligned_4_le(__v, __p);
-}
-
-static inline void __put_unaligned_8_be(const unsigned long long __v, register __u8 *__p)
-{
-       /*
-        * tradeoff: 8 bytes of stack for all unaligned puts (2
-        * instructions), or an extra register in the long long
-        * case - go for the extra register.
-        */
-       __put_unaligned_4_be(__v >> 32, __p);
-       __put_unaligned_4_be(__v, __p+4);
-}
-
-/*
- * Try to store an unaligned value as efficiently as possible.
- */
-#define __put_unaligned_le(val,ptr)                                    \
-       ({                                                      \
-               (void)sizeof(*(ptr) = (val));                   \
-               switch (sizeof(*(ptr))) {                       \
-               case 1:                                         \
-                       *(ptr) = (val);                         \
-                       break;                                  \
-               case 2: __put_unaligned_2_le((__force u16)(val),(__u8 *)(ptr)); \
-                       break;                                  \
-               case 4: __put_unaligned_4_le((__force u32)(val),(__u8 *)(ptr)); \
-                       break;                                  \
-               case 8: __put_unaligned_8_le((__force u64)(val),(__u8 *)(ptr)); \
-                       break;                                  \
-               default: __bug_unaligned_x(ptr);                \
-                       break;                                  \
-               }                                               \
-               (void) 0;                                       \
-       })
-
-#define __put_unaligned_be(val,ptr)                                    \
-       ({                                                      \
-               (void)sizeof(*(ptr) = (val));                   \
-               switch (sizeof(*(ptr))) {                       \
-               case 1:                                         \
-                       *(ptr) = (val);                         \
-                       break;                                  \
-               case 2: __put_unaligned_2_be((__force u16)(val),(__u8 *)(ptr)); \
-                       break;                                  \
-               case 4: __put_unaligned_4_be((__force u32)(val),(__u8 *)(ptr)); \
-                       break;                                  \
-               case 8: __put_unaligned_8_be((__force u64)(val),(__u8 *)(ptr)); \
-                       break;                                  \
-               default: __bug_unaligned_x(ptr);                \
-                       break;                                  \
-               }                                               \
-               (void) 0;                                       \
-       })
+#include <linux/unaligned/le_byteshift.h>
+#include <linux/unaligned/be_byteshift.h>
+#include <linux/unaligned/generic.h>
 
 /*
  * Select endianness
@@ -178,4 +16,4 @@ static inline void __put_unaligned_8_be(const unsigned long long __v, register _
 #define put_unaligned  __put_unaligned_be
 #endif
 
-#endif
+#endif /* _ASM_ARM_UNALIGNED_H */
index 36f5fd430543ec5d088335f52d357d58e7c75ea7..041877290470f18b3867234e9ff3459d97df8d28 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_AVR32_UNALIGNED_H
-#define __ASM_AVR32_UNALIGNED_H
+#ifndef _ASM_AVR32_UNALIGNED_H
+#define _ASM_AVR32_UNALIGNED_H
 
 /*
  * AVR32 can handle some unaligned accesses, depending on the
  * optimize word loads in general.
  */
 
-#include <asm-generic/unaligned.h>
+#include <linux/unaligned/be_struct.h>
+#include <linux/unaligned/le_byteshift.h>
+#include <linux/unaligned/generic.h>
 
-#endif /* __ASM_AVR32_UNALIGNED_H */
+#define get_unaligned  __get_unaligned_be
+#define put_unaligned  __put_unaligned_be
+
+#endif /* _ASM_AVR32_UNALIGNED_H */
index 10081dc241ef6d5430a1c5db68518e5cde4b34c6..fd8a1d634945dd916e5b6204c8e266a8c245fbec 100644 (file)
@@ -1,6 +1,11 @@
-#ifndef __BFIN_UNALIGNED_H
-#define __BFIN_UNALIGNED_H
+#ifndef _ASM_BLACKFIN_UNALIGNED_H
+#define _ASM_BLACKFIN_UNALIGNED_H
 
-#include <asm-generic/unaligned.h>
+#include <linux/unaligned/le_struct.h>
+#include <linux/unaligned/be_byteshift.h>
+#include <linux/unaligned/generic.h>
 
-#endif                         /* __BFIN_UNALIGNED_H */
+#define get_unaligned  __get_unaligned_le
+#define put_unaligned  __put_unaligned_le
+
+#endif /* _ASM_BLACKFIN_UNALIGNED_H */
index 7fbbb399f6f18c94ff1b0fc6557665d7ba7a1d83..7b3f3fec567ca4fd3a742f2ea6fef986e2ac3fb9 100644 (file)
@@ -1,16 +1,13 @@
-#ifndef __CRIS_UNALIGNED_H
-#define __CRIS_UNALIGNED_H
+#ifndef _ASM_CRIS_UNALIGNED_H
+#define _ASM_CRIS_UNALIGNED_H
 
 /*
  * CRIS can do unaligned accesses itself. 
- *
- * The strange macros are there to make sure these can't
- * be misused in a way that makes them not work on other
- * architectures where unaligned accesses aren't as simple.
  */
+#include <linux/unaligned/access_ok.h>
+#include <linux/unaligned/generic.h>
 
-#define get_unaligned(ptr) (*(ptr))
+#define get_unaligned  __get_unaligned_le
+#define put_unaligned  __put_unaligned_le
 
-#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
-
-#endif
+#endif /* _ASM_CRIS_UNALIGNED_H */
index dc8e9c9bf6bd9a54402db5ecb90619e89efbcb1d..64ccc736f2d87309667fae654b2d472d0ae075d3 100644 (file)
  * 2 of the License, or (at your option) any later version.
  */
 
-#ifndef _ASM_UNALIGNED_H
-#define _ASM_UNALIGNED_H
+#ifndef _ASM_FRV_UNALIGNED_H
+#define _ASM_FRV_UNALIGNED_H
 
+#include <linux/unaligned/le_byteshift.h>
+#include <linux/unaligned/be_byteshift.h>
+#include <linux/unaligned/generic.h>
 
-/*
- * Unaligned accesses on uClinux can't be performed in a fault handler - the
- * CPU detects them as imprecise exceptions making this impossible.
- *
- * With the FR451, however, they are precise, and so we used to fix them up in
- * the memory access fault handler.  However, instruction bundling make this
- * impractical.  So, now we fall back to using memcpy.
- */
-#ifdef CONFIG_MMU
-
-/*
- * The asm statement in the macros below is a way to get GCC to copy a
- * value from one variable to another without having any clue it's
- * actually doing so, so that it won't have any idea that the values
- * in the two variables are related.
- */
-
-#define get_unaligned(ptr) ({                          \
-       typeof((*(ptr))) __x;                           \
-       void *__ptrcopy;                                \
-       asm("" : "=r" (__ptrcopy) : "0" (ptr));         \
-       memcpy(&__x, __ptrcopy, sizeof(*(ptr)));        \
-       __x;                                            \
-})
-
-#define put_unaligned(val, ptr) ({                     \
-       typeof((*(ptr))) __x = (val);                   \
-       void *__ptrcopy;                                \
-       asm("" : "=r" (__ptrcopy) : "0" (ptr));         \
-       memcpy(__ptrcopy, &__x, sizeof(*(ptr)));        \
-})
-
-extern int handle_misalignment(unsigned long esr0, unsigned long ear0, unsigned long epcr0);
-
-#else
-
-#define get_unaligned(ptr)                                                     \
-({                                                                             \
-       typeof(*(ptr)) x;                                                       \
-       const char *__p = (const char *) (ptr);                                 \
-                                                                               \
-       switch (sizeof(x)) {                                                    \
-       case 1:                                                                 \
-               x = *(ptr);                                                     \
-               break;                                                          \
-       case 2:                                                                 \
-       {                                                                       \
-               uint8_t a;                                                      \
-               asm("   ldub%I2         %M2,%0          \n"                     \
-                   "   ldub%I3.p       %M3,%1          \n"                     \
-                   "   slli            %0,#8,%0        \n"                     \
-                   "   or              %0,%1,%0        \n"                     \
-                   : "=&r"(x), "=&r"(a)                                        \
-                   : "m"(__p[0]),  "m"(__p[1])                                 \
-                   );                                                          \
-               break;                                                          \
-       }                                                                       \
-                                                                               \
-       case 4:                                                                 \
-       {                                                                       \
-               uint8_t a;                                                      \
-               asm("   ldub%I2         %M2,%0          \n"                     \
-                   "   ldub%I3.p       %M3,%1          \n"                     \
-                   "   slli            %0,#8,%0        \n"                     \
-                   "   or              %0,%1,%0        \n"                     \
-                   "   ldub%I4.p       %M4,%1          \n"                     \
-                   "   slli            %0,#8,%0        \n"                     \
-                   "   or              %0,%1,%0        \n"                     \
-                   "   ldub%I5.p       %M5,%1          \n"                     \
-                   "   slli            %0,#8,%0        \n"                     \
-                   "   or              %0,%1,%0        \n"                     \
-                   : "=&r"(x), "=&r"(a)                                        \
-                   : "m"(__p[0]),  "m"(__p[1]), "m"(__p[2]), "m"(__p[3])       \
-                   );                                                          \
-               break;                                                          \
-       }                                                                       \
-                                                                               \
-       case 8:                                                                 \
-       {                                                                       \
-               union { uint64_t x; u32 y[2]; } z;                              \
-               uint8_t a;                                                      \
-               asm("   ldub%I3         %M3,%0          \n"                     \
-                   "   ldub%I4.p       %M4,%2          \n"                     \
-                   "   slli            %0,#8,%0        \n"                     \
-                   "   or              %0,%2,%0        \n"                     \
-                   "   ldub%I5.p       %M5,%2          \n"                     \
-                   "   slli            %0,#8,%0        \n"                     \
-                   "   or              %0,%2,%0        \n"                     \
-                   "   ldub%I6.p       %M6,%2          \n"                     \
-                   "   slli            %0,#8,%0        \n"                     \
-                   "   or              %0,%2,%0        \n"                     \
-                   "   ldub%I7         %M7,%1          \n"                     \
-                   "   ldub%I8.p       %M8,%2          \n"                     \
-                   "   slli            %1,#8,%1        \n"                     \
-                   "   or              %1,%2,%1        \n"                     \
-                   "   ldub%I9.p       %M9,%2          \n"                     \
-                   "   slli            %1,#8,%1        \n"                     \
-                   "   or              %1,%2,%1        \n"                     \
-                   "   ldub%I10.p      %M10,%2         \n"                     \
-                   "   slli            %1,#8,%1        \n"                     \
-                   "   or              %1,%2,%1        \n"                     \
-                   : "=&r"(z.y[0]), "=&r"(z.y[1]), "=&r"(a)                    \
-                   : "m"(__p[0]), "m"(__p[1]), "m"(__p[2]), "m"(__p[3]),       \
-                     "m"(__p[4]), "m"(__p[5]), "m"(__p[6]), "m"(__p[7])        \
-                   );                                                          \
-               x = z.x;                                                        \
-               break;                                                          \
-       }                                                                       \
-                                                                               \
-       default:                                                                \
-               x = 0;                                                          \
-               BUG();                                                          \
-               break;                                                          \
-       }                                                                       \
-                                                                               \
-       x;                                                                      \
-})
-
-#define put_unaligned(val, ptr)                                                                \
-do {                                                                                   \
-       char *__p = (char *) (ptr);                                                     \
-       int x;                                                                          \
-                                                                                       \
-       switch (sizeof(*ptr)) {                                                         \
-       case 2:                                                                         \
-       {                                                                               \
-               asm("   stb%I1.p        %0,%M1          \n"                             \
-                   "   srli            %0,#8,%0        \n"                             \
-                   "   stb%I2          %0,%M2          \n"                             \
-                   : "=r"(x), "=m"(__p[1]),  "=m"(__p[0])                              \
-                   : "0"(val)                                                          \
-                   );                                                                  \
-               break;                                                                  \
-       }                                                                               \
-                                                                                       \
-       case 4:                                                                         \
-       {                                                                               \
-               asm("   stb%I1.p        %0,%M1          \n"                             \
-                   "   srli            %0,#8,%0        \n"                             \
-                   "   stb%I2.p        %0,%M2          \n"                             \
-                   "   srli            %0,#8,%0        \n"                             \
-                   "   stb%I3.p        %0,%M3          \n"                             \
-                   "   srli            %0,#8,%0        \n"                             \
-                   "   stb%I4          %0,%M4          \n"                             \
-                   : "=r"(x), "=m"(__p[3]),  "=m"(__p[2]), "=m"(__p[1]), "=m"(__p[0])  \
-                   : "0"(val)                                                          \
-                   );                                                                  \
-               break;                                                                  \
-       }                                                                               \
-                                                                                       \
-       case 8:                                                                         \
-       {                                                                               \
-               uint32_t __high, __low;                                                 \
-               __high = (uint64_t)val >> 32;                                           \
-               __low = val & 0xffffffff;                                               \
-               asm("   stb%I2.p        %0,%M2          \n"                             \
-                   "   srli            %0,#8,%0        \n"                             \
-                   "   stb%I3.p        %0,%M3          \n"                             \
-                   "   srli            %0,#8,%0        \n"                             \
-                   "   stb%I4.p        %0,%M4          \n"                             \
-                   "   srli            %0,#8,%0        \n"                             \
-                   "   stb%I5.p        %0,%M5          \n"                             \
-                   "   srli            %0,#8,%0        \n"                             \
-                   "   stb%I6.p        %1,%M6          \n"                             \
-                   "   srli            %1,#8,%1        \n"                             \
-                   "   stb%I7.p        %1,%M7          \n"                             \
-                   "   srli            %1,#8,%1        \n"                             \
-                   "   stb%I8.p        %1,%M8          \n"                             \
-                   "   srli            %1,#8,%1        \n"                             \
-                   "   stb%I9          %1,%M9          \n"                             \
-                   : "=&r"(__low), "=&r"(__high), "=m"(__p[7]), "=m"(__p[6]),          \
-                     "=m"(__p[5]), "=m"(__p[4]), "=m"(__p[3]), "=m"(__p[2]),           \
-                     "=m"(__p[1]), "=m"(__p[0])                                        \
-                   : "0"(__low), "1"(__high)                                           \
-                   );                                                                  \
-               break;                                                                  \
-       }                                                                               \
-                                                                                       \
-        default:                                                                       \
-               *(ptr) = (val);                                                         \
-               break;                                                                  \
-       }                                                                               \
-} while(0)
-
-#endif
+#define get_unaligned  __get_unaligned_be
+#define put_unaligned  __put_unaligned_be
 
-#endif
+#endif /* _ASM_FRV_UNALIGNED_H */
index 15e6f253dda4090622d93c0d688e4350da4411ad..c9f369c4bd7ed3d9fd2e65ff5ee65634d48cf77e 100644 (file)
@@ -17,8 +17,6 @@
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/find.h>
 
-#ifdef __KERNEL__
-
 #ifndef _LINUX_BITOPS_H
 #error only <linux/bitops.h> can be included directly
 #endif
@@ -32,6 +30,4 @@
 #include <asm-generic/bitops/ext2-atomic.h>
 #include <asm-generic/bitops/minix.h>
 
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_GENERIC_BITOPS_H */
index f422df0956a27025deb4c6cdbbc5a47646f74c9e..3c2344f48136d98351f92b6e9d678e29c052658c 100644 (file)
@@ -1,11 +1,9 @@
 #ifndef _ASM_GENERIC_FUTEX_H
 #define _ASM_GENERIC_FUTEX_H
 
-#ifdef __KERNEL__
-
 #include <linux/futex.h>
+#include <linux/uaccess.h>
 #include <asm/errno.h>
-#include <asm/uaccess.h>
 
 static inline int
 futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
@@ -56,4 +54,3 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 }
 
 #endif
-#endif
index cd027298beb13bcc5ac043f78b826cfb8dfdace5..864181385579891496f396bee440d8b3b0884117 100644 (file)
  */
 #define _IOC_NRBITS    8
 #define _IOC_TYPEBITS  8
-#define _IOC_SIZEBITS  14
-#define _IOC_DIRBITS   2
+
+/*
+ * Let any architecture override either of the following before
+ * including this file.
+ */
+
+#ifndef _IOC_SIZEBITS
+# define _IOC_SIZEBITS 14
+#endif
+
+#ifndef _IOC_DIRBITS
+# define _IOC_DIRBITS  2
+#endif
 
 #define _IOC_NRMASK    ((1 << _IOC_NRBITS)-1)
 #define _IOC_TYPEMASK  ((1 << _IOC_TYPEBITS)-1)
 #define _IOC_DIRSHIFT  (_IOC_SIZESHIFT+_IOC_SIZEBITS)
 
 /*
- * Direction bits.
+ * Direction bits, which any architecture can choose to override
+ * before including this file.
  */
-#define _IOC_NONE      0U
-#define _IOC_WRITE     1U
-#define _IOC_READ      2U
+
+#ifndef _IOC_NONE
+# define _IOC_NONE     0U
+#endif
+
+#ifndef _IOC_WRITE
+# define _IOC_WRITE    1U
+#endif
+
+#ifndef _IOC_READ
+# define _IOC_READ     2U
+#endif
 
 #define _IOC(dir,type,nr,size) \
        (((dir)  << _IOC_DIRSHIFT) | \
index 52226e14bd7dba34b483a77ba22424e4241f8145..ae060c62aff1af5e5db8a4366b73d305b8f362db 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef __ASM_MEMORY_MODEL_H
 #define __ASM_MEMORY_MODEL_H
 
-#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
 #if defined(CONFIG_FLATMEM)
@@ -81,6 +80,5 @@ extern unsigned long page_to_pfn(struct page *page);
 #endif /* CONFIG_OUT_OF_LINE_PFN_TO_PAGE */
 
 #endif /* __ASSEMBLY__ */
-#endif /* __KERNEL__ */
 
 #endif
index a96b5d986b6e8b1f05fb896adacae85b4243149c..14db733b8e68e7df3cb95bb685eb97cc0125a094 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_GENERIC_PAGE_H
 #define _ASM_GENERIC_PAGE_H
 
-#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
 #include <linux/compiler.h>
@@ -21,6 +20,5 @@ static __inline__ __attribute_const__ int get_order(unsigned long size)
 }
 
 #endif /* __ASSEMBLY__ */
-#endif /* __KERNEL__ */
 
 #endif /* _ASM_GENERIC_PAGE_H */
index dd1bed860e6487a3c325c2dfd66570efe8616066..be4af0029ac0b451cd89c91f239d3eca231a2e62 100644 (file)
@@ -12,8 +12,6 @@
 #ifndef __ASM_RTC_H__
 #define __ASM_RTC_H__
 
-#ifdef __KERNEL__
-
 #include <linux/mc146818rtc.h>
 #include <linux/rtc.h>
 #include <linux/bcd.h>
@@ -213,5 +211,4 @@ static inline int set_rtc_pll(struct rtc_pll_info *pll)
        return -EINVAL;
 }
 
-#endif /* __KERNEL__ */
 #endif /* __ASM_RTC_H__ */
diff --git a/include/asm-generic/unaligned.h b/include/asm-generic/unaligned.h
deleted file mode 100644 (file)
index 2fe1b2e..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-#ifndef _ASM_GENERIC_UNALIGNED_H_
-#define _ASM_GENERIC_UNALIGNED_H_
-
-/*
- * For the benefit of those who are trying to port Linux to another
- * architecture, here are some C-language equivalents. 
- *
- * This is based almost entirely upon Richard Henderson's
- * asm-alpha/unaligned.h implementation.  Some comments were
- * taken from David Mosberger's asm-ia64/unaligned.h header.
- */
-
-#include <linux/types.h>
-
-/* 
- * The main single-value unaligned transfer routines.
- */
-#define get_unaligned(ptr) \
-       __get_unaligned((ptr), sizeof(*(ptr)))
-#define put_unaligned(x,ptr) \
-       ((void)sizeof(*(ptr)=(x)),\
-       __put_unaligned((__force __u64)(x), (ptr), sizeof(*(ptr))))
-
-/*
- * This function doesn't actually exist.  The idea is that when
- * someone uses the macros below with an unsupported size (datatype),
- * the linker will alert us to the problem via an unresolved reference
- * error.
- */
-extern void bad_unaligned_access_length(void) __attribute__((noreturn));
-
-struct __una_u64 { __u64 x __attribute__((packed)); };
-struct __una_u32 { __u32 x __attribute__((packed)); };
-struct __una_u16 { __u16 x __attribute__((packed)); };
-
-/*
- * Elemental unaligned loads 
- */
-
-static inline __u64 __uldq(const __u64 *addr)
-{
-       const struct __una_u64 *ptr = (const struct __una_u64 *) addr;
-       return ptr->x;
-}
-
-static inline __u32 __uldl(const __u32 *addr)
-{
-       const struct __una_u32 *ptr = (const struct __una_u32 *) addr;
-       return ptr->x;
-}
-
-static inline __u16 __uldw(const __u16 *addr)
-{
-       const struct __una_u16 *ptr = (const struct __una_u16 *) addr;
-       return ptr->x;
-}
-
-/*
- * Elemental unaligned stores 
- */
-
-static inline void __ustq(__u64 val, __u64 *addr)
-{
-       struct __una_u64 *ptr = (struct __una_u64 *) addr;
-       ptr->x = val;
-}
-
-static inline void __ustl(__u32 val, __u32 *addr)
-{
-       struct __una_u32 *ptr = (struct __una_u32 *) addr;
-       ptr->x = val;
-}
-
-static inline void __ustw(__u16 val, __u16 *addr)
-{
-       struct __una_u16 *ptr = (struct __una_u16 *) addr;
-       ptr->x = val;
-}
-
-#define __get_unaligned(ptr, size) ({          \
-       const void *__gu_p = ptr;               \
-       __u64 __val;                            \
-       switch (size) {                         \
-       case 1:                                 \
-               __val = *(const __u8 *)__gu_p;  \
-               break;                          \
-       case 2:                                 \
-               __val = __uldw(__gu_p);         \
-               break;                          \
-       case 4:                                 \
-               __val = __uldl(__gu_p);         \
-               break;                          \
-       case 8:                                 \
-               __val = __uldq(__gu_p);         \
-               break;                          \
-       default:                                \
-               bad_unaligned_access_length();  \
-       };                                      \
-       (__force __typeof__(*(ptr)))__val;      \
-})
-
-#define __put_unaligned(val, ptr, size)                \
-({                                             \
-       void *__gu_p = ptr;                     \
-       switch (size) {                         \
-       case 1:                                 \
-               *(__u8 *)__gu_p = (__force __u8)val;            \
-               break;                          \
-       case 2:                                 \
-               __ustw((__force __u16)val, __gu_p);             \
-               break;                          \
-       case 4:                                 \
-               __ustl((__force __u32)val, __gu_p);             \
-               break;                          \
-       case 8:                                 \
-               __ustq(val, __gu_p);            \
-               break;                          \
-       default:                                \
-               bad_unaligned_access_length();  \
-       };                                      \
-       (void)0;                                \
-})
-
-#endif /* _ASM_GENERIC_UNALIGNED_H */
index ffb67f472070c995d362d7cc6ac2698276c8becd..b8d06c70c2da44b5e78ea629c40467951e6e4c77 100644 (file)
@@ -1,15 +1,11 @@
-#ifndef __H8300_UNALIGNED_H
-#define __H8300_UNALIGNED_H
+#ifndef _ASM_H8300_UNALIGNED_H
+#define _ASM_H8300_UNALIGNED_H
 
+#include <linux/unaligned/be_memmove.h>
+#include <linux/unaligned/le_byteshift.h>
+#include <linux/unaligned/generic.h>
 
-/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
+#define get_unaligned  __get_unaligned_be
+#define put_unaligned  __put_unaligned_be
 
-#define get_unaligned(ptr) \
-  ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
-
-#define put_unaligned(val, ptr)                                \
-  ({ __typeof__(*(ptr)) __tmp = (val);                 \
-     memmove((ptr), &__tmp, sizeof(*(ptr)));           \
-     (void)0; })
-
-#endif
+#endif /* _ASM_H8300_UNALIGNED_H */
index f1735a22d0ea28cd08ce5be1413c78cd1e397061..9f0df9bd46b7f1a772f5a121782a73b70b753af4 100644 (file)
@@ -23,10 +23,30 @@ dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr,
 {
        dma_free_coherent(dev, size, cpu_addr, dma_handle);
 }
-#define dma_map_single         platform_dma_map_single
-#define dma_map_sg             platform_dma_map_sg
-#define dma_unmap_single       platform_dma_unmap_single
-#define dma_unmap_sg           platform_dma_unmap_sg
+#define dma_map_single_attrs   platform_dma_map_single_attrs
+static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
+                                       size_t size, int dir)
+{
+       return dma_map_single_attrs(dev, cpu_addr, size, dir, NULL);
+}
+#define dma_map_sg_attrs       platform_dma_map_sg_attrs
+static inline int dma_map_sg(struct device *dev, struct scatterlist *sgl,
+                            int nents, int dir)
+{
+       return dma_map_sg_attrs(dev, sgl, nents, dir, NULL);
+}
+#define dma_unmap_single_attrs platform_dma_unmap_single_attrs
+static inline void dma_unmap_single(struct device *dev, dma_addr_t cpu_addr,
+                                   size_t size, int dir)
+{
+       return dma_unmap_single_attrs(dev, cpu_addr, size, dir, NULL);
+}
+#define dma_unmap_sg_attrs     platform_dma_unmap_sg_attrs
+static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sgl,
+                               int nents, int dir)
+{
+       return dma_unmap_sg_attrs(dev, sgl, nents, dir, NULL);
+}
 #define dma_sync_single_for_cpu        platform_dma_sync_single_for_cpu
 #define dma_sync_sg_for_cpu    platform_dma_sync_sg_for_cpu
 #define dma_sync_single_for_device platform_dma_sync_single_for_device
index 8a98a26541391ed17cbcebf97b0b98ef5a1efa31..c7f0f062239cd541112ecbe10cdd34dc54672eec 100644 (file)
@@ -2,9 +2,9 @@
 #define _ASM_FUTEX_H
 
 #include <linux/futex.h>
+#include <linux/uaccess.h>
 #include <asm/errno.h>
 #include <asm/system.h>
-#include <asm/uaccess.h>
 
 #define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg) \
 do {                                                                   \
index c201a2020aa49e1a8a30deff30892b143e3dc157..9f020eb825c58c89224bfd10923a1872d77cb3ad 100644 (file)
@@ -22,6 +22,7 @@ struct pci_bus;
 struct task_struct;
 struct pci_dev;
 struct msi_desc;
+struct dma_attrs;
 
 typedef void ia64_mv_setup_t (char **);
 typedef void ia64_mv_cpu_init_t (void);
@@ -56,6 +57,11 @@ typedef void ia64_mv_dma_sync_sg_for_device (struct device *, struct scatterlist
 typedef int ia64_mv_dma_mapping_error (dma_addr_t dma_addr);
 typedef int ia64_mv_dma_supported (struct device *, u64);
 
+typedef dma_addr_t ia64_mv_dma_map_single_attrs (struct device *, void *, size_t, int, struct dma_attrs *);
+typedef void ia64_mv_dma_unmap_single_attrs (struct device *, dma_addr_t, size_t, int, struct dma_attrs *);
+typedef int ia64_mv_dma_map_sg_attrs (struct device *, struct scatterlist *, int, int, struct dma_attrs *);
+typedef void ia64_mv_dma_unmap_sg_attrs (struct device *, struct scatterlist *, int, int, struct dma_attrs *);
+
 /*
  * WARNING: The legacy I/O space is _architected_.  Platforms are
  * expected to follow this architected model (see Section 10.7 in the
@@ -136,10 +142,10 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *);
 #  define platform_dma_init            ia64_mv.dma_init
 #  define platform_dma_alloc_coherent  ia64_mv.dma_alloc_coherent
 #  define platform_dma_free_coherent   ia64_mv.dma_free_coherent
-#  define platform_dma_map_single      ia64_mv.dma_map_single
-#  define platform_dma_unmap_single    ia64_mv.dma_unmap_single
-#  define platform_dma_map_sg          ia64_mv.dma_map_sg
-#  define platform_dma_unmap_sg                ia64_mv.dma_unmap_sg
+#  define platform_dma_map_single_attrs        ia64_mv.dma_map_single_attrs
+#  define platform_dma_unmap_single_attrs      ia64_mv.dma_unmap_single_attrs
+#  define platform_dma_map_sg_attrs    ia64_mv.dma_map_sg_attrs
+#  define platform_dma_unmap_sg_attrs  ia64_mv.dma_unmap_sg_attrs
 #  define platform_dma_sync_single_for_cpu ia64_mv.dma_sync_single_for_cpu
 #  define platform_dma_sync_sg_for_cpu ia64_mv.dma_sync_sg_for_cpu
 #  define platform_dma_sync_single_for_device ia64_mv.dma_sync_single_for_device
@@ -190,10 +196,10 @@ struct ia64_machine_vector {
        ia64_mv_dma_init *dma_init;
        ia64_mv_dma_alloc_coherent *dma_alloc_coherent;
        ia64_mv_dma_free_coherent *dma_free_coherent;
-       ia64_mv_dma_map_single *dma_map_single;
-       ia64_mv_dma_unmap_single *dma_unmap_single;
-       ia64_mv_dma_map_sg *dma_map_sg;
-       ia64_mv_dma_unmap_sg *dma_unmap_sg;
+       ia64_mv_dma_map_single_attrs *dma_map_single_attrs;
+       ia64_mv_dma_unmap_single_attrs *dma_unmap_single_attrs;
+       ia64_mv_dma_map_sg_attrs *dma_map_sg_attrs;
+       ia64_mv_dma_unmap_sg_attrs *dma_unmap_sg_attrs;
        ia64_mv_dma_sync_single_for_cpu *dma_sync_single_for_cpu;
        ia64_mv_dma_sync_sg_for_cpu *dma_sync_sg_for_cpu;
        ia64_mv_dma_sync_single_for_device *dma_sync_single_for_device;
@@ -240,10 +246,10 @@ struct ia64_machine_vector {
        platform_dma_init,                      \
        platform_dma_alloc_coherent,            \
        platform_dma_free_coherent,             \
-       platform_dma_map_single,                \
-       platform_dma_unmap_single,              \
-       platform_dma_map_sg,                    \
-       platform_dma_unmap_sg,                  \
+       platform_dma_map_single_attrs,          \
+       platform_dma_unmap_single_attrs,        \
+       platform_dma_map_sg_attrs,              \
+       platform_dma_unmap_sg_attrs,            \
        platform_dma_sync_single_for_cpu,       \
        platform_dma_sync_sg_for_cpu,           \
        platform_dma_sync_single_for_device,    \
@@ -292,9 +298,13 @@ extern ia64_mv_dma_init                    swiotlb_init;
 extern ia64_mv_dma_alloc_coherent      swiotlb_alloc_coherent;
 extern ia64_mv_dma_free_coherent       swiotlb_free_coherent;
 extern ia64_mv_dma_map_single          swiotlb_map_single;
+extern ia64_mv_dma_map_single_attrs    swiotlb_map_single_attrs;
 extern ia64_mv_dma_unmap_single                swiotlb_unmap_single;
+extern ia64_mv_dma_unmap_single_attrs  swiotlb_unmap_single_attrs;
 extern ia64_mv_dma_map_sg              swiotlb_map_sg;
+extern ia64_mv_dma_map_sg_attrs                swiotlb_map_sg_attrs;
 extern ia64_mv_dma_unmap_sg            swiotlb_unmap_sg;
+extern ia64_mv_dma_unmap_sg_attrs      swiotlb_unmap_sg_attrs;
 extern ia64_mv_dma_sync_single_for_cpu swiotlb_sync_single_for_cpu;
 extern ia64_mv_dma_sync_sg_for_cpu     swiotlb_sync_sg_for_cpu;
 extern ia64_mv_dma_sync_single_for_device swiotlb_sync_single_for_device;
@@ -340,17 +350,17 @@ extern ia64_mv_dma_supported              swiotlb_dma_supported;
 #ifndef platform_dma_free_coherent
 # define platform_dma_free_coherent    swiotlb_free_coherent
 #endif
-#ifndef platform_dma_map_single
-# define platform_dma_map_single       swiotlb_map_single
+#ifndef platform_dma_map_single_attrs
+# define platform_dma_map_single_attrs swiotlb_map_single_attrs
 #endif
-#ifndef platform_dma_unmap_single
-# define platform_dma_unmap_single     swiotlb_unmap_single
+#ifndef platform_dma_unmap_single_attrs
+# define platform_dma_unmap_single_attrs       swiotlb_unmap_single_attrs
 #endif
-#ifndef platform_dma_map_sg
-# define platform_dma_map_sg           swiotlb_map_sg
+#ifndef platform_dma_map_sg_attrs
+# define platform_dma_map_sg_attrs     swiotlb_map_sg_attrs
 #endif
-#ifndef platform_dma_unmap_sg
-# define platform_dma_unmap_sg         swiotlb_unmap_sg
+#ifndef platform_dma_unmap_sg_attrs
+# define platform_dma_unmap_sg_attrs   swiotlb_unmap_sg_attrs
 #endif
 #ifndef platform_dma_sync_single_for_cpu
 # define platform_dma_sync_single_for_cpu      swiotlb_sync_single_for_cpu
index e90daf9ce340cc0cb2b6433ceb247c314d2ccc65..2f57f5144b9fbc55363734d0dbf0920bac497fa6 100644 (file)
@@ -4,10 +4,10 @@
 extern ia64_mv_setup_t                 dig_setup;
 extern ia64_mv_dma_alloc_coherent      sba_alloc_coherent;
 extern ia64_mv_dma_free_coherent       sba_free_coherent;
-extern ia64_mv_dma_map_single          sba_map_single;
-extern ia64_mv_dma_unmap_single                sba_unmap_single;
-extern ia64_mv_dma_map_sg              sba_map_sg;
-extern ia64_mv_dma_unmap_sg            sba_unmap_sg;
+extern ia64_mv_dma_map_single_attrs    sba_map_single_attrs;
+extern ia64_mv_dma_unmap_single_attrs  sba_unmap_single_attrs;
+extern ia64_mv_dma_map_sg_attrs                sba_map_sg_attrs;
+extern ia64_mv_dma_unmap_sg_attrs      sba_unmap_sg_attrs;
 extern ia64_mv_dma_supported           sba_dma_supported;
 extern ia64_mv_dma_mapping_error       sba_dma_mapping_error;
 
@@ -23,10 +23,10 @@ extern ia64_mv_dma_mapping_error    sba_dma_mapping_error;
 #define platform_dma_init                      machvec_noop
 #define platform_dma_alloc_coherent            sba_alloc_coherent
 #define platform_dma_free_coherent             sba_free_coherent
-#define platform_dma_map_single                        sba_map_single
-#define platform_dma_unmap_single              sba_unmap_single
-#define platform_dma_map_sg                    sba_map_sg
-#define platform_dma_unmap_sg                  sba_unmap_sg
+#define platform_dma_map_single_attrs          sba_map_single_attrs
+#define platform_dma_unmap_single_attrs                sba_unmap_single_attrs
+#define platform_dma_map_sg_attrs              sba_map_sg_attrs
+#define platform_dma_unmap_sg_attrs            sba_unmap_sg_attrs
 #define platform_dma_sync_single_for_cpu       machvec_dma_sync_single
 #define platform_dma_sync_sg_for_cpu           machvec_dma_sync_sg
 #define platform_dma_sync_single_for_device    machvec_dma_sync_single
index f00a34a148ff338b276f98e3ee70d96f79ea749b..a842cdda827bd8203f95d4e367e1a8eed47d8764 100644 (file)
@@ -4,10 +4,10 @@
 extern ia64_mv_setup_t                         dig_setup;
 extern ia64_mv_dma_alloc_coherent              hwsw_alloc_coherent;
 extern ia64_mv_dma_free_coherent               hwsw_free_coherent;
-extern ia64_mv_dma_map_single                  hwsw_map_single;
-extern ia64_mv_dma_unmap_single                        hwsw_unmap_single;
-extern ia64_mv_dma_map_sg                      hwsw_map_sg;
-extern ia64_mv_dma_unmap_sg                    hwsw_unmap_sg;
+extern ia64_mv_dma_map_single_attrs            hwsw_map_single_attrs;
+extern ia64_mv_dma_unmap_single_attrs          hwsw_unmap_single_attrs;
+extern ia64_mv_dma_map_sg_attrs                        hwsw_map_sg_attrs;
+extern ia64_mv_dma_unmap_sg_attrs              hwsw_unmap_sg_attrs;
 extern ia64_mv_dma_supported                   hwsw_dma_supported;
 extern ia64_mv_dma_mapping_error               hwsw_dma_mapping_error;
 extern ia64_mv_dma_sync_single_for_cpu         hwsw_sync_single_for_cpu;
@@ -28,10 +28,10 @@ extern ia64_mv_dma_sync_sg_for_device               hwsw_sync_sg_for_device;
 #define platform_dma_init                      machvec_noop
 #define platform_dma_alloc_coherent            hwsw_alloc_coherent
 #define platform_dma_free_coherent             hwsw_free_coherent
-#define platform_dma_map_single                        hwsw_map_single
-#define platform_dma_unmap_single              hwsw_unmap_single
-#define platform_dma_map_sg                    hwsw_map_sg
-#define platform_dma_unmap_sg                  hwsw_unmap_sg
+#define platform_dma_map_single_attrs          hwsw_map_single_attrs
+#define platform_dma_unmap_single_attrs                hwsw_unmap_single_attrs
+#define platform_dma_map_sg_attrs              hwsw_map_sg_attrs
+#define platform_dma_unmap_sg_attrs            hwsw_unmap_sg_attrs
 #define platform_dma_supported                 hwsw_dma_supported
 #define platform_dma_mapping_error             hwsw_dma_mapping_error
 #define platform_dma_sync_single_for_cpu       hwsw_sync_single_for_cpu
index 61439a7f5b08a76263983695d23ec7562bbea96e..781308ea7b88baad9f1c6f58eeb039c4fc60f048 100644 (file)
@@ -57,10 +57,10 @@ extern ia64_mv_readl_t __sn_readl_relaxed;
 extern ia64_mv_readq_t __sn_readq_relaxed;
 extern ia64_mv_dma_alloc_coherent      sn_dma_alloc_coherent;
 extern ia64_mv_dma_free_coherent       sn_dma_free_coherent;
-extern ia64_mv_dma_map_single          sn_dma_map_single;
-extern ia64_mv_dma_unmap_single                sn_dma_unmap_single;
-extern ia64_mv_dma_map_sg              sn_dma_map_sg;
-extern ia64_mv_dma_unmap_sg            sn_dma_unmap_sg;
+extern ia64_mv_dma_map_single_attrs    sn_dma_map_single_attrs;
+extern ia64_mv_dma_unmap_single_attrs  sn_dma_unmap_single_attrs;
+extern ia64_mv_dma_map_sg_attrs                sn_dma_map_sg_attrs;
+extern ia64_mv_dma_unmap_sg_attrs      sn_dma_unmap_sg_attrs;
 extern ia64_mv_dma_sync_single_for_cpu sn_dma_sync_single_for_cpu;
 extern ia64_mv_dma_sync_sg_for_cpu     sn_dma_sync_sg_for_cpu;
 extern ia64_mv_dma_sync_single_for_device sn_dma_sync_single_for_device;
@@ -113,10 +113,10 @@ extern ia64_mv_pci_fixup_bus_t            sn_pci_fixup_bus;
 #define platform_dma_init              machvec_noop
 #define platform_dma_alloc_coherent    sn_dma_alloc_coherent
 #define platform_dma_free_coherent     sn_dma_free_coherent
-#define platform_dma_map_single                sn_dma_map_single
-#define platform_dma_unmap_single      sn_dma_unmap_single
-#define platform_dma_map_sg            sn_dma_map_sg
-#define platform_dma_unmap_sg          sn_dma_unmap_sg
+#define platform_dma_map_single_attrs  sn_dma_map_single_attrs
+#define platform_dma_unmap_single_attrs        sn_dma_unmap_single_attrs
+#define platform_dma_map_sg_attrs      sn_dma_map_sg_attrs
+#define platform_dma_unmap_sg_attrs    sn_dma_unmap_sg_attrs
 #define platform_dma_sync_single_for_cpu sn_dma_sync_single_for_cpu
 #define platform_dma_sync_sg_for_cpu   sn_dma_sync_sg_for_cpu
 #define platform_dma_sync_single_for_device sn_dma_sync_single_for_device
index 6da8069a0f77ff6c78074cb45bf36868445f4d9d..f30e05583869e8fe3431ac9f0aef20e90e0edc22 100644 (file)
@@ -101,7 +101,6 @@ extern void tsk_clear_notify_resume(struct task_struct *tsk);
 #define TIF_SYSCALL_TRACE      2       /* syscall trace active */
 #define TIF_SYSCALL_AUDIT      3       /* syscall auditing active */
 #define TIF_SINGLESTEP         4       /* restore singlestep on return to user mode */
-#define TIF_RESTORE_SIGMASK    5       /* restore signal mask in do_signal() */
 #define TIF_NOTIFY_RESUME      6       /* resumption notification requested */
 #define TIF_POLLING_NRFLAG     16      /* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE             17
@@ -109,6 +108,7 @@ extern void tsk_clear_notify_resume(struct task_struct *tsk);
 #define TIF_DB_DISABLED                19      /* debug trap disabled for fsyscall */
 #define TIF_FREEZE             20      /* is freezing for suspend */
 #define TIF_RESTORE_RSE                21      /* user RBS is newer than kernel RBS */
+#define TIF_RESTORE_SIGMASK    22      /* restore signal mask in do_signal() */
 
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
@@ -126,8 +126,7 @@ extern void tsk_clear_notify_resume(struct task_struct *tsk);
 
 /* "work to do on user-return" bits */
 #define TIF_ALLWORK_MASK       (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SYSCALL_AUDIT|\
-                                _TIF_NEED_RESCHED| _TIF_SYSCALL_TRACE|\
-                                _TIF_RESTORE_SIGMASK)
+                                _TIF_NEED_RESCHED|_TIF_SYSCALL_TRACE)
 /* like TIF_ALLWORK_BITS but sans TIF_SYSCALL_TRACE or TIF_SYSCALL_AUDIT */
 #define TIF_WORK_MASK          (TIF_ALLWORK_MASK&~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT))
 
index f2f72ef2a8974cc3496dc0fd92435626f708a7e8..32863b3bb1d3e9bdd8cba30a5eb3356b3cbbb467 100644 (file)
@@ -116,6 +116,8 @@ void build_cpu_to_node_map(void);
 #define smt_capable()                          (smp_num_siblings > 1)
 #endif
 
+extern void arch_fix_phys_package_id(int num, u32 slot);
+
 #define pcibus_to_cpumask(bus) (pcibus_to_node(bus) == -1 ? \
                                        CPU_MASK_ALL : \
                                        node_to_cpumask(pcibus_to_node(bus)) \
index bb855988810353220b9d7d238e3d40d2eec1985c..7bddc7f5858469630fc27787fedda38edf7636e0 100644 (file)
@@ -1,6 +1,11 @@
 #ifndef _ASM_IA64_UNALIGNED_H
 #define _ASM_IA64_UNALIGNED_H
 
-#include <asm-generic/unaligned.h>
+#include <linux/unaligned/le_struct.h>
+#include <linux/unaligned/be_byteshift.h>
+#include <linux/unaligned/generic.h>
+
+#define get_unaligned  __get_unaligned_le
+#define put_unaligned  __put_unaligned_le
 
 #endif /* _ASM_IA64_UNALIGNED_H */
index b82d923b73c1c5b6ad8d1d0599331b72440f0d3f..13d7e65ca3cce3e76bbf2346c37651ad95e01e9c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001-2005 Silicon Graphics, Inc.  All rights reserved.
+ * Copyright (C) 2001-2008 Silicon Graphics, Inc.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
@@ -8,5 +8,5 @@
  * Prototypes for the uncached page allocator
  */
 
-extern unsigned long uncached_alloc_page(int nid);
-extern void uncached_free_page(unsigned long);
+extern unsigned long uncached_alloc_page(int starting_nid, int n_pages);
+extern void uncached_free_page(unsigned long uc_addr, int n_pages);
index fccc180c3913ff84a67af1139d0bc43a3eeed3a5..377eb20d1ec6dfdac60920f04bc6dbd2e4175ac0 100644 (file)
@@ -1,19 +1,18 @@
 #ifndef _ASM_M32R_UNALIGNED_H
 #define _ASM_M32R_UNALIGNED_H
 
-/*
- * For the benefit of those who are trying to port Linux to another
- * architecture, here are some C-language equivalents.
- */
-
-#include <asm/string.h>
-
-#define get_unaligned(ptr) \
-  ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
-
-#define put_unaligned(val, ptr)                                \
-  ({ __typeof__(*(ptr)) __tmp = (val);                 \
-     memmove((ptr), &__tmp, sizeof(*(ptr)));           \
-     (void)0; })
+#if defined(__LITTLE_ENDIAN__)
+# include <linux/unaligned/le_memmove.h>
+# include <linux/unaligned/be_byteshift.h>
+# include <linux/unaligned/generic.h>
+# define get_unaligned __get_unaligned_le
+# define put_unaligned __put_unaligned_le
+#else
+# include <linux/unaligned/be_memmove.h>
+# include <linux/unaligned/le_byteshift.h>
+# include <linux/unaligned/generic.h>
+# define get_unaligned __get_unaligned_be
+# define put_unaligned __put_unaligned_be
+#endif
 
 #endif /* _ASM_M32R_UNALIGNED_H */
index 804cb3f888fe60d4a32ad314418bd809972d008f..77698f2dc33cca2367653b7b15633982870d783e 100644 (file)
@@ -1,16 +1,13 @@
-#ifndef __M68K_UNALIGNED_H
-#define __M68K_UNALIGNED_H
+#ifndef _ASM_M68K_UNALIGNED_H
+#define _ASM_M68K_UNALIGNED_H
 
 /*
  * The m68k can do unaligned accesses itself.
- *
- * The strange macros are there to make sure these can't
- * be misused in a way that makes them not work on other
- * architectures where unaligned accesses aren't as simple.
  */
+#include <linux/unaligned/access_ok.h>
+#include <linux/unaligned/generic.h>
 
-#define get_unaligned(ptr) (*(ptr))
+#define get_unaligned  __get_unaligned_be
+#define put_unaligned  __put_unaligned_be
 
-#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
-
-#endif
+#endif /* _ASM_M68K_UNALIGNED_H */
index 869e9dd24f544f276001793aeea97356c6230c0c..eb1ea4cb9a598e20af365400ff51479a41ad262f 100644 (file)
@@ -1,23 +1,25 @@
-#ifndef __M68K_UNALIGNED_H
-#define __M68K_UNALIGNED_H
+#ifndef _ASM_M68KNOMMU_UNALIGNED_H
+#define _ASM_M68KNOMMU_UNALIGNED_H
 
 
 #ifdef CONFIG_COLDFIRE
+#include <linux/unaligned/be_struct.h>
+#include <linux/unaligned/le_byteshift.h>
+#include <linux/unaligned/generic.h>
 
-#include <asm-generic/unaligned.h>
+#define get_unaligned  __get_unaligned_be
+#define put_unaligned  __put_unaligned_be
 
 #else
 /*
  * The m68k can do unaligned accesses itself. 
- *
- * The strange macros are there to make sure these can't
- * be misused in a way that makes them not work on other
- * architectures where unaligned accesses aren't as simple.
  */
+#include <linux/unaligned/access_ok.h>
+#include <linux/unaligned/generic.h>
 
-#define get_unaligned(ptr) (*(ptr))
-#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
+#define get_unaligned  __get_unaligned_be
+#define put_unaligned  __put_unaligned_be
 
 #endif
 
-#endif
+#endif /* _ASM_M68KNOMMU_UNALIGNED_H */
index 17f082cfea85c055cda99f1fcd6305331daa726e..b9cce90346cfc334819f44e95c4308f96b8f9533 100644 (file)
@@ -11,9 +11,9 @@
 #ifdef __KERNEL__
 
 #include <linux/futex.h>
+#include <linux/uaccess.h>
 #include <asm/barrier.h>
 #include <asm/errno.h>
-#include <asm/uaccess.h>
 #include <asm/war.h>
 
 #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)             \
index 3249049e93aafcc8eeb345b07a6d220f29a7398e..792404948571847f8b9feb6067a7f63bb862e013 100644 (file)
@@ -5,25 +5,24 @@
  *
  * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
  */
-#ifndef __ASM_GENERIC_UNALIGNED_H
-#define __ASM_GENERIC_UNALIGNED_H
+#ifndef _ASM_MIPS_UNALIGNED_H
+#define _ASM_MIPS_UNALIGNED_H
 
 #include <linux/compiler.h>
+#if defined(__MIPSEB__)
+# include <linux/unaligned/be_struct.h>
+# include <linux/unaligned/le_byteshift.h>
+# include <linux/unaligned/generic.h>
+# define get_unaligned __get_unaligned_be
+# define put_unaligned __put_unaligned_be
+#elif defined(__MIPSEL__)
+# include <linux/unaligned/le_struct.h>
+# include <linux/unaligned/be_byteshift.h>
+# include <linux/unaligned/generic.h>
+# define get_unaligned __get_unaligned_le
+# define put_unaligned __put_unaligned_le
+#else
+#  error "MIPS, but neither __MIPSEB__, nor __MIPSEL__???"
+#endif
 
-#define get_unaligned(ptr)                                     \
-({                                                             \
-       struct __packed {                                       \
-               typeof(*(ptr)) __v;                             \
-       } *__p = (void *) (ptr);                                \
-       __p->__v;                                               \
-})
-
-#define put_unaligned(val, ptr)                                        \
-do {                                                           \
-       struct __packed {                                       \
-               typeof(*(ptr)) __v;                             \
-       } *__p = (void *) (ptr);                                \
-       __p->__v = (val);                                       \
-} while(0)
-
-#endif /* __ASM_GENERIC_UNALIGNED_H */
+#endif /* _ASM_MIPS_UNALIGNED_H */
index cad3afbd035f1744d7c3751d252ab74c257347e3..0df671318ae4952d8a395da4c5c01ab61f040f11 100644 (file)
  * as published by the Free Software Foundation; either version
  * 2 of the Licence, or (at your option) any later version.
  */
-#ifndef _ASM_UNALIGNED_H
-#define _ASM_UNALIGNED_H
+#ifndef _ASM_MN10300_UNALIGNED_H
+#define _ASM_MN10300_UNALIGNED_H
 
-#include <asm/types.h>
+#include <linux/unaligned/access_ok.h>
+#include <linux/unaligned/generic.h>
 
-#if 0
-extern int __bug_unaligned_x(void *ptr);
+#define get_unaligned  __get_unaligned_le
+#define put_unaligned  __put_unaligned_le
 
-/*
- * What is the most efficient way of loading/storing an unaligned value?
- *
- * That is the subject of this file.  Efficiency here is defined as
- * minimum code size with minimum register usage for the common cases.
- * It is currently not believed that long longs are common, so we
- * trade efficiency for the chars, shorts and longs against the long
- * longs.
- *
- * Current stats with gcc 2.7.2.2 for these functions:
- *
- *     ptrsize get:    code    regs    put:    code    regs
- *     1               1       1               1       2
- *     2               3       2               3       2
- *     4               7       3               7       3
- *     8               20      6               16      6
- *
- * gcc 2.95.1 seems to code differently:
- *
- *     ptrsize get:    code    regs    put:    code    regs
- *     1               1       1               1       2
- *     2               3       2               3       2
- *     4               7       4               7       4
- *     8               19      8               15      6
- *
- * which may or may not be more efficient (depending upon whether
- * you can afford the extra registers).  Hopefully the gcc 2.95
- * is inteligent enough to decide if it is better to use the
- * extra register, but evidence so far seems to suggest otherwise.
- *
- * Unfortunately, gcc is not able to optimise the high word
- * out of long long >> 32, or the low word from long long << 32
- */
-
-#define __get_unaligned_2(__p)                                 \
-       (__p[0] | __p[1] << 8)
-
-#define __get_unaligned_4(__p)                                 \
-       (__p[0] | __p[1] << 8 | __p[2] << 16 | __p[3] << 24)
-
-#define get_unaligned(ptr)                                     \
-({                                                             \
-       unsigned int __v1, __v2;                                \
-       __typeof__(*(ptr)) __v;                                 \
-       __u8 *__p = (__u8 *)(ptr);                              \
-                                                               \
-       switch (sizeof(*(ptr))) {                               \
-       case 1: __v = *(ptr);                   break;          \
-       case 2: __v = __get_unaligned_2(__p);   break;          \
-       case 4: __v = __get_unaligned_4(__p);   break;          \
-       case 8:                                                 \
-               __v2 = __get_unaligned_4((__p+4));              \
-               __v1 = __get_unaligned_4(__p);                  \
-               __v = ((unsigned long long)__v2 << 32 | __v1);  \
-               break;                                          \
-       default: __v = __bug_unaligned_x(__p);  break;          \
-       }                                                       \
-       __v;                                                    \
-})
-
-
-static inline void __put_unaligned_2(__u32 __v, register __u8 *__p)
-{
-       *__p++ = __v;
-       *__p++ = __v >> 8;
-}
-
-static inline void __put_unaligned_4(__u32 __v, register __u8 *__p)
-{
-       __put_unaligned_2(__v >> 16, __p + 2);
-       __put_unaligned_2(__v, __p);
-}
-
-static inline void __put_unaligned_8(const unsigned long long __v, __u8 *__p)
-{
-       /*
-        * tradeoff: 8 bytes of stack for all unaligned puts (2
-        * instructions), or an extra register in the long long
-        * case - go for the extra register.
-        */
-       __put_unaligned_4(__v >> 32, __p + 4);
-       __put_unaligned_4(__v, __p);
-}
-
-/*
- * Try to store an unaligned value as efficiently as possible.
- */
-#define put_unaligned(val, ptr)                                                \
-       ({                                                              \
-               switch (sizeof(*(ptr))) {                               \
-               case 1:                                                 \
-                       *(ptr) = (val);                                 \
-                       break;                                          \
-               case 2:                                                 \
-                       __put_unaligned_2((val), (__u8 *)(ptr));        \
-                       break;                                          \
-               case 4:                                                 \
-                       __put_unaligned_4((val), (__u8 *)(ptr));        \
-                       break;                                          \
-               case 8:                                                 \
-                       __put_unaligned_8((val), (__u8 *)(ptr));        \
-                       break;                                          \
-               default:                                                \
-                       __bug_unaligned_x(ptr);                         \
-                       break;                                          \
-               }                                                       \
-               (void) 0;                                               \
-       })
-
-
-#else
-
-#define get_unaligned(ptr) (*(ptr))
-#define put_unaligned(val, ptr) ({ *(ptr) = (val); (void) 0; })
-
-#endif
-
-#endif
+#endif /* _ASM_MN10300_UNALIGNED_H */
index fdc6d055ef7f2af68872f2f195d8b417ebb9558f..0c705c3a55efc01305dbea4e14eecf63c0f3f05e 100644 (file)
@@ -4,8 +4,8 @@
 #ifdef __KERNEL__
 
 #include <linux/futex.h>
+#include <linux/uaccess.h>
 #include <asm/errno.h>
-#include <asm/uaccess.h>
 
 static inline int
 futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
index 53c905838d9330a07598c1310c7567e3ddde8591..dfc5d3321a54bb72bba3b234586f2332142293ea 100644 (file)
@@ -1,7 +1,11 @@
-#ifndef _ASM_PARISC_UNALIGNED_H_
-#define _ASM_PARISC_UNALIGNED_H_
+#ifndef _ASM_PARISC_UNALIGNED_H
+#define _ASM_PARISC_UNALIGNED_H
 
-#include <asm-generic/unaligned.h>
+#include <linux/unaligned/be_struct.h>
+#include <linux/unaligned/le_byteshift.h>
+#include <linux/unaligned/generic.h>
+#define get_unaligned  __get_unaligned_be
+#define put_unaligned  __put_unaligned_be
 
 #ifdef __KERNEL__
 struct pt_regs;
@@ -9,4 +13,4 @@ void handle_unaligned(struct pt_regs *regs);
 int check_unaligned(struct pt_regs *regs);
 #endif
 
-#endif /* _ASM_PARISC_UNALIGNED_H_ */
+#endif /* _ASM_PARISC_UNALIGNED_H */
index 3f3673fd3ff34abef169c139c71302084b2cc874..6d406c5c5de40390853e18cf2f4a7c03899cd381 100644 (file)
@@ -4,9 +4,9 @@
 #ifdef __KERNEL__
 
 #include <linux/futex.h>
+#include <linux/uaccess.h>
 #include <asm/errno.h>
 #include <asm/synch.h>
-#include <asm/uaccess.h>
 #include <asm/asm-compat.h>
 
 #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
index b5c03127a9b9402b57e88de81c79454aabaa833b..5089deb8fec3f0fcf744d1647eea5475202555a1 100644 (file)
@@ -619,8 +619,6 @@ struct pt_regs;
 
 #define __ARCH_HAS_DO_SOFTIRQ
 
-extern void __do_softirq(void);
-
 #ifdef CONFIG_IRQSTACKS
 /*
  * Per-cpu stacks for handling hard and soft interrupts.
index 6c95dfa2652f332cbdcf73b04565d7c3e546cad0..5f1b1e3c21374d5a1833ed00c9af9d5c06a35123 100644 (file)
@@ -5,15 +5,12 @@
 
 /*
  * The PowerPC can do unaligned accesses itself in big endian mode.
- *
- * The strange macros are there to make sure these can't
- * be misused in a way that makes them not work on other
- * architectures where unaligned accesses aren't as simple.
  */
+#include <linux/unaligned/access_ok.h>
+#include <linux/unaligned/generic.h>
 
-#define get_unaligned(ptr) (*(ptr))
-
-#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
+#define get_unaligned  __get_unaligned_be
+#define put_unaligned  __put_unaligned_be
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_UNALIGNED_H */
index 0a518915bf90f1087466444caf0809a8b9b3a02b..99bbed99a3b2d288d17a7154c174dd7de514c390 100644 (file)
@@ -89,7 +89,6 @@ static inline struct thread_info *current_thread_info(void)
  * thread information flags bit numbers
  */
 #define TIF_SYSCALL_TRACE      0       /* syscall trace active */
-#define TIF_RESTORE_SIGMASK    1       /* restore signal mask in do_signal() */
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
 #define TIF_RESTART_SVC                4       /* restart svc with new svc number */
@@ -101,6 +100,7 @@ static inline struct thread_info *current_thread_info(void)
                                           TIF_NEED_RESCHED */
 #define TIF_31BIT              18      /* 32bit process */ 
 #define TIF_MEMDIE             19
+#define TIF_RESTORE_SIGMASK    20      /* restore signal mask in do_signal() */
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
index 8ee86dbedd1fe91fd87f3d99b9689466b6bd577c..da9627afe5d8578ea951037f7ddbba33fb8e6b08 100644 (file)
@@ -1,24 +1,13 @@
-/*
- *  include/asm-s390/unaligned.h
- *
- *  S390 version
- *
- *  Derived from "include/asm-i386/unaligned.h"
- */
-
-#ifndef __S390_UNALIGNED_H
-#define __S390_UNALIGNED_H
+#ifndef _ASM_S390_UNALIGNED_H
+#define _ASM_S390_UNALIGNED_H
 
 /*
  * The S390 can do unaligned accesses itself. 
- *
- * The strange macros are there to make sure these can't
- * be misused in a way that makes them not work on other
- * architectures where unaligned accesses aren't as simple.
  */
+#include <linux/unaligned/access_ok.h>
+#include <linux/unaligned/generic.h>
 
-#define get_unaligned(ptr) (*(ptr))
-
-#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
+#define get_unaligned  __get_unaligned_be
+#define put_unaligned  __put_unaligned_be
 
-#endif
+#endif /* _ASM_S390_UNALIGNED_H */
index 74ed3681d33c3298a0b35f5d514fff8251320994..68256ec5fa35b3e2c46ead9e2566810583351dcd 100644 (file)
@@ -4,8 +4,8 @@
 #ifdef __KERNEL__
 
 #include <linux/futex.h>
+#include <linux/uaccess.h>
 #include <asm/errno.h>
-#include <asm/uaccess.h>
 
 /* XXX: UP variants, fix for SH-4A and SMP.. */
 #include <asm/futex-irq.h>
index 5250e3063b42d32ad5dfd751121930920918d93a..c1641a01d50ff738d9f4bacd628b59155f400cce 100644 (file)
@@ -1,7 +1,19 @@
-#ifndef __ASM_SH_UNALIGNED_H
-#define __ASM_SH_UNALIGNED_H
+#ifndef _ASM_SH_UNALIGNED_H
+#define _ASM_SH_UNALIGNED_H
 
 /* SH can't handle unaligned accesses. */
-#include <asm-generic/unaligned.h>
+#ifdef __LITTLE_ENDIAN__
+# include <linux/unaligned/le_struct.h>
+# include <linux/unaligned/be_byteshift.h>
+# include <linux/unaligned/generic.h>
+# define get_unaligned __get_unaligned_le
+# define put_unaligned __put_unaligned_le
+#else
+# include <linux/unaligned/be_struct.h>
+# include <linux/unaligned/le_byteshift.h>
+# include <linux/unaligned/generic.h>
+# define get_unaligned __get_unaligned_be
+# define put_unaligned __put_unaligned_be
+#endif
 
-#endif /* __ASM_SH_UNALIGNED_H */
+#endif /* _ASM_SH_UNALIGNED_H */
index b6f8eddd30af2f59bd6e81b548c664da1bef5501..11d2d5fb59029beede89e4870f6c74776924a9db 100644 (file)
@@ -1,6 +1,10 @@
-#ifndef _ASM_SPARC_UNALIGNED_H_
-#define _ASM_SPARC_UNALIGNED_H_
+#ifndef _ASM_SPARC_UNALIGNED_H
+#define _ASM_SPARC_UNALIGNED_H
 
-#include <asm-generic/unaligned.h>
+#include <linux/unaligned/be_struct.h>
+#include <linux/unaligned/le_byteshift.h>
+#include <linux/unaligned/generic.h>
+#define get_unaligned  __get_unaligned_be
+#define put_unaligned  __put_unaligned_be
 
 #endif /* _ASM_SPARC_UNALIGNED_H */
index df1097d6ffbe63258dc566924cedb9e393438d5f..d8378935ae90918149a3099b46b38e11f5aa7d42 100644 (file)
@@ -2,9 +2,9 @@
 #define _SPARC64_FUTEX_H
 
 #include <linux/futex.h>
+#include <linux/uaccess.h>
 #include <asm/errno.h>
 #include <asm/system.h>
-#include <asm/uaccess.h>
 
 #define __futex_cas_op(insn, ret, oldval, uaddr, oparg)        \
        __asm__ __volatile__(                           \
index 1ed3ba5377728d97734c2e94f65dbc93b64a210c..edcebb09441e9e1451c0e1cee3c4329ebd7b2128 100644 (file)
@@ -1,6 +1,10 @@
-#ifndef _ASM_SPARC64_UNALIGNED_H_
-#define _ASM_SPARC64_UNALIGNED_H_
+#ifndef _ASM_SPARC64_UNALIGNED_H
+#define _ASM_SPARC64_UNALIGNED_H
 
-#include <asm-generic/unaligned.h>
+#include <linux/unaligned/be_struct.h>
+#include <linux/unaligned/le_byteshift.h>
+#include <linux/unaligned/generic.h>
+#define get_unaligned  __get_unaligned_be
+#define put_unaligned  __put_unaligned_be
 
 #endif /* _ASM_SPARC64_UNALIGNED_H */
index 1d2497c57274b599be081a5a5e4d794261f9ba29..a47196974e393d9826a53f92d026fe8602e3ab4f 100644 (file)
@@ -1,6 +1,6 @@
-#ifndef __UM_UNALIGNED_H
-#define __UM_UNALIGNED_H
+#ifndef _ASM_UM_UNALIGNED_H
+#define _ASM_UM_UNALIGNED_H
 
 #include "asm/arch/unaligned.h"
 
-#endif
+#endif /* _ASM_UM_UNALIGNED_H */
index e30b18653a94bf8cde19b2573888692d1d46d55a..53122b28491ec7b64a31d897d38866d040214702 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * include/asm-v850/unaligned.h -- Unaligned memory access
- *
  *  Copyright (C) 2001  NEC Corporation
  *  Copyright (C) 2001  Miles Bader <miles@gnu.org>
  *
  * Public License.  See the file COPYING in the main directory of this
  * archive for more details.
  *
- * This file is a copy of the arm version, include/asm-arm/unaligned.h
- *
  * Note that some v850 chips support unaligned access, but it seems too
  * annoying to use.
  */
+#ifndef _ASM_V850_UNALIGNED_H
+#define _ASM_V850_UNALIGNED_H
 
-#ifndef __V850_UNALIGNED_H__
-#define __V850_UNALIGNED_H__
-
-#include <asm/types.h>
-
-extern int __bug_unaligned_x(void *ptr);
-
-/*
- * What is the most efficient way of loading/storing an unaligned value?
- *
- * That is the subject of this file.  Efficiency here is defined as
- * minimum code size with minimum register usage for the common cases.
- * It is currently not believed that long longs are common, so we
- * trade efficiency for the chars, shorts and longs against the long
- * longs.
- *
- * Current stats with gcc 2.7.2.2 for these functions:
- *
- *     ptrsize get:    code    regs    put:    code    regs
- *     1               1       1               1       2
- *     2               3       2               3       2
- *     4               7       3               7       3
- *     8               20      6               16      6
- *
- * gcc 2.95.1 seems to code differently:
- *
- *     ptrsize get:    code    regs    put:    code    regs
- *     1               1       1               1       2
- *     2               3       2               3       2
- *     4               7       4               7       4
- *     8               19      8               15      6
- *
- * which may or may not be more efficient (depending upon whether
- * you can afford the extra registers).  Hopefully the gcc 2.95
- * is inteligent enough to decide if it is better to use the
- * extra register, but evidence so far seems to suggest otherwise.
- *
- * Unfortunately, gcc is not able to optimise the high word
- * out of long long >> 32, or the low word from long long << 32
- */
-
-#define __get_unaligned_2(__p)                                 \
-       (__p[0] | __p[1] << 8)
-
-#define __get_unaligned_4(__p)                                 \
-       (__p[0] | __p[1] << 8 | __p[2] << 16 | __p[3] << 24)
-
-#define get_unaligned(ptr)                                     \
-       ({                                                      \
-               __typeof__(*(ptr)) __v;                         \
-               __u8 *__p = (__u8 *)(ptr);                      \
-               switch (sizeof(*(ptr))) {                       \
-               case 1: __v = *(ptr);                   break;  \
-               case 2: __v = __get_unaligned_2(__p);   break;  \
-               case 4: __v = __get_unaligned_4(__p);   break;  \
-               case 8: {                                       \
-                               unsigned int __v1, __v2;        \
-                               __v2 = __get_unaligned_4((__p+4)); \
-                               __v1 = __get_unaligned_4(__p);  \
-                               __v = ((unsigned long long)__v2 << 32 | __v1);  \
-                       }                                       \
-                       break;                                  \
-               default: __v = __bug_unaligned_x(__p);  break;  \
-               }                                               \
-               __v;                                            \
-       })
-
-
-static inline void __put_unaligned_2(__u32 __v, register __u8 *__p)
-{
-       *__p++ = __v;
-       *__p++ = __v >> 8;
-}
-
-static inline void __put_unaligned_4(__u32 __v, register __u8 *__p)
-{
-       __put_unaligned_2(__v >> 16, __p + 2);
-       __put_unaligned_2(__v, __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
-        * instructions), or an extra register in the long long
-        * case - go for the extra register.
-        */
-       __put_unaligned_4(__v >> 32, __p+4);
-       __put_unaligned_4(__v, __p);
-}
-
-/*
- * Try to store an unaligned value as efficiently as possible.
- */
-#define put_unaligned(val,ptr)                                 \
-       ({                                                      \
-               switch (sizeof(*(ptr))) {                       \
-               case 1:                                         \
-                       *(ptr) = (val);                         \
-                       break;                                  \
-               case 2: __put_unaligned_2((val),(__u8 *)(ptr)); \
-                       break;                                  \
-               case 4: __put_unaligned_4((val),(__u8 *)(ptr)); \
-                       break;                                  \
-               case 8: __put_unaligned_8((val),(__u8 *)(ptr)); \
-                       break;                                  \
-               default: __bug_unaligned_x(ptr);                \
-                       break;                                  \
-               }                                               \
-               (void) 0;                                       \
-       })
+#include <linux/unaligned/be_byteshift.h>
+#include <linux/unaligned/le_byteshift.h>
+#include <linux/unaligned/generic.h>
 
+#define get_unaligned  __get_unaligned_le
+#define put_unaligned  __put_unaligned_le
 
-#endif /* __V850_UNALIGNED_H__ */
+#endif /* _ASM_V850_UNALIGNED_H */
index ac0fbf24d722a36f3f0ee20e7060b5aace6bced1..e7a76b37b333cc8b40295d7379f8cbb46b241a29 100644 (file)
@@ -4,12 +4,12 @@
 #ifdef __KERNEL__
 
 #include <linux/futex.h>
+#include <linux/uaccess.h>
 
 #include <asm/asm.h>
 #include <asm/errno.h>
 #include <asm/processor.h>
 #include <asm/system.h>
-#include <asm/uaccess.h>
 
 #define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg)    \
        asm volatile("1:\t" insn "\n"                           \
diff --git a/include/asm-x86/olpc.h b/include/asm-x86/olpc.h
new file mode 100644 (file)
index 0000000..97d4713
--- /dev/null
@@ -0,0 +1,132 @@
+/* OLPC machine specific definitions */
+
+#ifndef ASM_OLPC_H_
+#define ASM_OLPC_H_
+
+#include <asm/geode.h>
+
+struct olpc_platform_t {
+       int flags;
+       uint32_t boardrev;
+       int ecver;
+};
+
+#define OLPC_F_PRESENT         0x01
+#define OLPC_F_DCON            0x02
+#define OLPC_F_VSA             0x04
+
+#ifdef CONFIG_OLPC
+
+extern struct olpc_platform_t olpc_platform_info;
+
+/*
+ * OLPC board IDs contain the major build number within the mask 0x0ff0,
+ * and the minor build number withing 0x000f.  Pre-builds have a minor
+ * number less than 8, and normal builds start at 8.  For example, 0x0B10
+ * is a PreB1, and 0x0C18 is a C1.
+ */
+
+static inline uint32_t olpc_board(uint8_t id)
+{
+       return (id << 4) | 0x8;
+}
+
+static inline uint32_t olpc_board_pre(uint8_t id)
+{
+       return id << 4;
+}
+
+static inline int machine_is_olpc(void)
+{
+       return (olpc_platform_info.flags & OLPC_F_PRESENT) ? 1 : 0;
+}
+
+/*
+ * The DCON is OLPC's Display Controller.  It has a number of unique
+ * features that we might want to take advantage of..
+ */
+static inline int olpc_has_dcon(void)
+{
+       return (olpc_platform_info.flags & OLPC_F_DCON) ? 1 : 0;
+}
+
+/*
+ * The VSA is software from AMD that typical Geode bioses will include.
+ * It is used to emulate the PCI bus, VGA, etc.  OLPC's Open Firmware does
+ * not include the VSA; instead, PCI is emulated by the kernel.
+ *
+ * The VSA is described further in arch/x86/pci/olpc.c.
+ */
+static inline int olpc_has_vsa(void)
+{
+       return (olpc_platform_info.flags & OLPC_F_VSA) ? 1 : 0;
+}
+
+/*
+ * The "Mass Production" version of OLPC's XO is identified as being model
+ * C2.  During the prototype phase, the following models (in chronological
+ * order) were created: A1, B1, B2, B3, B4, C1.  The A1 through B2 models
+ * were based on Geode GX CPUs, and models after that were based upon
+ * Geode LX CPUs.  There were also some hand-assembled models floating
+ * around, referred to as PreB1, PreB2, etc.
+ */
+static inline int olpc_board_at_least(uint32_t rev)
+{
+       return olpc_platform_info.boardrev >= rev;
+}
+
+#else
+
+static inline int machine_is_olpc(void)
+{
+       return 0;
+}
+
+static inline int olpc_has_dcon(void)
+{
+       return 0;
+}
+
+static inline int olpc_has_vsa(void)
+{
+       return 0;
+}
+
+#endif
+
+/* EC related functions */
+
+extern int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,
+               unsigned char *outbuf, size_t outlen);
+
+extern int olpc_ec_mask_set(uint8_t bits);
+extern int olpc_ec_mask_unset(uint8_t bits);
+
+/* EC commands */
+
+#define EC_FIRMWARE_REV                0x08
+
+/* SCI source values */
+
+#define EC_SCI_SRC_EMPTY       0x00
+#define EC_SCI_SRC_GAME                0x01
+#define EC_SCI_SRC_BATTERY     0x02
+#define EC_SCI_SRC_BATSOC      0x04
+#define EC_SCI_SRC_BATERR      0x08
+#define EC_SCI_SRC_EBOOK       0x10
+#define EC_SCI_SRC_WLAN                0x20
+#define EC_SCI_SRC_ACPWR       0x40
+#define EC_SCI_SRC_ALL         0x7F
+
+/* GPIO assignments */
+
+#define OLPC_GPIO_MIC_AC       geode_gpio(1)
+#define OLPC_GPIO_DCON_IRQ     geode_gpio(7)
+#define OLPC_GPIO_THRM_ALRM    geode_gpio(10)
+#define OLPC_GPIO_SMB_CLK      geode_gpio(14)
+#define OLPC_GPIO_SMB_DATA     geode_gpio(15)
+#define OLPC_GPIO_WORKAUX      geode_gpio(24)
+#define OLPC_GPIO_LID          geode_gpio(26)
+#define OLPC_GPIO_ECSCI                geode_gpio(27)
+
+#endif
index ddd8e248fc0a43bde4ec039beebbdfc500457e77..30bbde0cb34bfba7e272ad68be2dffad8ef20d0d 100644 (file)
@@ -19,6 +19,8 @@ struct pci_sysdata {
 };
 
 /* scan a bus after allocating a pci_sysdata for it */
+extern struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops,
+                                           int node);
 extern struct pci_bus *pci_scan_bus_with_sysdata(int busno);
 
 static inline int pci_domain_nr(struct pci_bus *bus)
index 53185996209664c82588904ca3429844696ab9b2..b6338829d1a8d866745c8b8126ff1d0995383828 100644 (file)
@@ -131,7 +131,6 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_EMU                5       /* syscall emulation active */
 #define TIF_SYSCALL_AUDIT      6       /* syscall auditing active */
 #define TIF_SECCOMP            7       /* secure computing */
-#define TIF_RESTORE_SIGMASK    8       /* restore signal mask in do_signal() */
 #define TIF_HRTICK_RESCHED     9       /* reprogram hrtick timer */
 #define TIF_MEMDIE             16
 #define TIF_DEBUG              17      /* uses debug registers */
@@ -151,7 +150,6 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_EMU       (1 << TIF_SYSCALL_EMU)
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP           (1 << TIF_SECCOMP)
-#define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
 #define _TIF_HRTICK_RESCHED    (1 << TIF_HRTICK_RESCHED)
 #define _TIF_DEBUG             (1 << TIF_DEBUG)
 #define _TIF_IO_BITMAP         (1 << TIF_IO_BITMAP)
@@ -188,9 +186,20 @@ static inline struct thread_info *current_thread_info(void)
                                           this quantum (SMP) */
 #define TS_POLLING             0x0002  /* True if in idle loop
                                           and not sleeping */
+#define TS_RESTORE_SIGMASK     0x0004  /* restore signal mask in do_signal() */
 
 #define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING)
 
+#ifndef __ASSEMBLY__
+#define HAVE_SET_RESTORE_SIGMASK       1
+static inline void set_restore_sigmask(void)
+{
+       struct thread_info *ti = current_thread_info();
+       ti->status |= TS_RESTORE_SIGMASK;
+       set_bit(TIF_SIGPENDING, &ti->flags);
+}
+#endif /* !__ASSEMBLY__ */
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_THREAD_INFO_H */
index ed664e874decb873d83bad65ba2eb5a549dab69d..cb69f70abba107889e2011e12e21ef70cefbe19a 100644 (file)
@@ -109,7 +109,6 @@ static inline struct thread_info *stack_thread_info(void)
 #define TIF_IRET               5       /* force IRET */
 #define TIF_SYSCALL_AUDIT      7       /* syscall auditing active */
 #define TIF_SECCOMP            8       /* secure computing */
-#define TIF_RESTORE_SIGMASK    9       /* restore signal mask in do_signal */
 #define TIF_MCE_NOTIFY         10      /* notify userspace of an MCE */
 #define TIF_HRTICK_RESCHED     11      /* reprogram hrtick timer */
 /* 16 free */
@@ -133,7 +132,6 @@ static inline struct thread_info *stack_thread_info(void)
 #define _TIF_IRET              (1 << TIF_IRET)
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP           (1 << TIF_SECCOMP)
-#define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
 #define _TIF_MCE_NOTIFY                (1 << TIF_MCE_NOTIFY)
 #define _TIF_HRTICK_RESCHED    (1 << TIF_HRTICK_RESCHED)
 #define _TIF_IA32              (1 << TIF_IA32)
@@ -178,9 +176,20 @@ static inline struct thread_info *stack_thread_info(void)
 #define TS_COMPAT              0x0002  /* 32bit syscall active */
 #define TS_POLLING             0x0004  /* true if in idle loop
                                           and not sleeping */
+#define TS_RESTORE_SIGMASK     0x0008  /* restore signal mask in do_signal() */
 
 #define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING)
 
+#ifndef __ASSEMBLY__
+#define HAVE_SET_RESTORE_SIGMASK       1
+static inline void set_restore_sigmask(void)
+{
+       struct thread_info *ti = current_thread_info();
+       ti->status |= TS_RESTORE_SIGMASK;
+       set_bit(TIF_SIGPENDING, &ti->flags);
+}
+#endif /* !__ASSEMBLY__ */
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_THREAD_INFO_H */
index 68779b048a3edba6f3371bb459735d8a170aec9f..bce72d7a958c21829aa79c041b4ac2fb06178421 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASMX86_TIME_H
 #define _ASMX86_TIME_H
 
-extern void (*late_time_init)(void);
 extern void hpet_time_init(void);
 
 #include <asm/mc146818rtc.h>
index 22073268b4814ec97a7ddab151e01c1807eabcc8..4f35a0fb4f22ac5ba6d459a45f4eb8971eb50cac 100644 (file)
@@ -193,9 +193,29 @@ extern cpumask_t cpu_coregroup_map(int cpu);
 #define topology_thread_siblings(cpu)          (per_cpu(cpu_sibling_map, cpu))
 #endif
 
+static inline void arch_fix_phys_package_id(int num, u32 slot)
+{
+}
+
+struct pci_bus;
+void set_pci_bus_resources_arch_default(struct pci_bus *b);
+
 #ifdef CONFIG_SMP
 #define mc_capable()                   (boot_cpu_data.x86_max_cores > 1)
 #define smt_capable()                  (smp_num_siblings > 1)
 #endif
 
+#ifdef CONFIG_NUMA
+extern int get_mp_bus_to_node(int busnum);
+extern void set_mp_bus_to_node(int busnum, int node);
+#else
+static inline int get_mp_bus_to_node(int busnum)
+{
+       return 0;
+}
+static inline void set_mp_bus_to_node(int busnum, int node)
+{
+}
+#endif
+
 #endif
index d2d8eb5b55f532365f9277b5f776109626f7ed4b..548873ab5fc1b0deabafc4b3dcbb23ee8cbf05db 100644 (file)
@@ -32,7 +32,7 @@ static inline cycles_t get_cycles(void)
        return ret;
 }
 
-static inline cycles_t vget_cycles(void)
+static __always_inline cycles_t vget_cycles(void)
 {
        /*
         * We only do VDSOs on TSC capable CPUs, so this shouldnt
index d270ffe727597474be2a85e8fcea665b14a122b3..a7bd416b4763832f0a9851df49e92c938b8c5232 100644 (file)
@@ -3,35 +3,12 @@
 
 /*
  * The x86 can do unaligned accesses itself.
- *
- * The strange macros are there to make sure these can't
- * be misused in a way that makes them not work on other
- * architectures where unaligned accesses aren't as simple.
  */
 
-/**
- * get_unaligned - get value from possibly mis-aligned location
- * @ptr: pointer to value
- *
- * This macro should be used for accessing values larger in size than
- * single bytes at locations that are expected to be improperly aligned,
- * e.g. retrieving a u16 value from a location not u16-aligned.
- *
- * Note that unaligned accesses can be very expensive on some architectures.
- */
-#define get_unaligned(ptr) (*(ptr))
+#include <linux/unaligned/access_ok.h>
+#include <linux/unaligned/generic.h>
 
-/**
- * put_unaligned - put value to a possibly mis-aligned location
- * @val: value to place
- * @ptr: pointer to location
- *
- * This macro should be used for placing values larger in size than
- * single bytes at locations that are expected to be improperly aligned,
- * e.g. writing a u16 value to a location not u16-aligned.
- *
- * Note that unaligned accesses can be very expensive on some architectures.
- */
-#define put_unaligned(val, ptr) ((void)(*(ptr) = (val)))
+#define get_unaligned __get_unaligned_le
+#define put_unaligned __put_unaligned_le
 
 #endif /* _ASM_X86_UNALIGNED_H */
index 28220890d0a6be20e1156fb1baacf654596071b9..8f3424fc5d1823df176ebf62662dec2d03b07d5d 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * include/asm-xtensa/unaligned.h
- *
  * Xtensa doesn't handle unaligned accesses efficiently.
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -9,20 +7,23 @@
  *
  * Copyright (C) 2001 - 2005 Tensilica Inc.
  */
+#ifndef _ASM_XTENSA_UNALIGNED_H
+#define _ASM_XTENSA_UNALIGNED_H
 
-#ifndef _XTENSA_UNALIGNED_H
-#define _XTENSA_UNALIGNED_H
-
-#include <linux/string.h>
-
-/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
-
-#define get_unaligned(ptr) \
-  ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
-
-#define put_unaligned(val, ptr)                                \
-  ({ __typeof__(*(ptr)) __tmp = (val);                 \
-     memmove((ptr), &__tmp, sizeof(*(ptr)));           \
-     (void)0; })
+#ifdef __XTENSA_EL__
+# include <linux/unaligned/le_memmove.h>
+# include <linux/unaligned/be_byteshift.h>
+# include <linux/unaligned/generic.h>
+# define get_unaligned __get_unaligned_le
+# define put_unaligned __put_unaligned_le
+#elif defined(__XTENSA_EB__)
+# include <linux/unaligned/be_memmove.h>
+# include <linux/unaligned/le_byteshift.h>
+# include <linux/unaligned/generic.h>
+# define get_unaligned __get_unaligned_be
+# define put_unaligned __put_unaligned_be
+#else
+# error processor byte order undefined!
+#endif
 
-#endif /* _XTENSA_UNALIGNED_H */
+#endif /* _ASM_XTENSA_UNALIGNED_H */
index bda6f04791d43e421efec9c5ced07bdd407f3eb4..78fade0a1e3528aaae16a306a47f22e91336e0e7 100644 (file)
@@ -20,6 +20,7 @@ header-y += affs_hardblocks.h
 header-y += aio_abi.h
 header-y += arcfb.h
 header-y += atmapi.h
+header-y += atmarp.h
 header-y += atmbr2684.h
 header-y += atmclip.h
 header-y += atm_eni.h
@@ -48,6 +49,7 @@ header-y += coff.h
 header-y += comstats.h
 header-y += const.h
 header-y += cgroupstats.h
+header-y += cramfs_fs.h
 header-y += cycx_cfm.h
 header-y += dlmconstants.h
 header-y += dlm_device.h
@@ -70,10 +72,12 @@ header-y += firewire-constants.h
 header-y += fuse.h
 header-y += genetlink.h
 header-y += gen_stats.h
+header-y += gfs2_ondisk.h
 header-y += gigaset_dev.h
 header-y += hysdn_if.h
 header-y += i2o-dev.h
 header-y += i8k.h
+header-y += if_addrlabel.h
 header-y += if_arcnet.h
 header-y += if_bonding.h
 header-y += if_cablemodem.h
@@ -91,6 +95,7 @@ header-y += if_tunnel.h
 header-y += in6.h
 header-y += in_route.h
 header-y += ioctl.h
+header-y += ip6_tunnel.h
 header-y += ipmi_msgdefs.h
 header-y += ipsec.h
 header-y += ipx.h
@@ -117,7 +122,6 @@ header-y += nfs2.h
 header-y += nfs4_mount.h
 header-y += nfs_mount.h
 header-y += nl80211.h
-header-y += oom.h
 header-y += param.h
 header-y += pci_regs.h
 header-y += pfkeyv2.h
@@ -166,7 +170,6 @@ unifdef-y += adfs_fs.h
 unifdef-y += agpgart.h
 unifdef-y += apm_bios.h
 unifdef-y += atalk.h
-unifdef-y += atmarp.h
 unifdef-y += atmdev.h
 unifdef-y += atm.h
 unifdef-y += atm_tcp.h
@@ -182,7 +185,6 @@ unifdef-y += cm4000_cs.h
 unifdef-y += cn_proc.h
 unifdef-y += coda.h
 unifdef-y += connector.h
-unifdef-y += cramfs_fs.h
 unifdef-y += cuda.h
 unifdef-y += cyclades.h
 unifdef-y += dccp.h
@@ -205,7 +207,6 @@ unifdef-y += futex.h
 unifdef-y += fs.h
 unifdef-y += gameport.h
 unifdef-y += generic_serial.h
-unifdef-y += gfs2_ondisk.h
 unifdef-y += hayesesp.h
 unifdef-y += hdlcdrv.h
 unifdef-y += hdlc.h
@@ -219,7 +220,6 @@ unifdef-y += i2c-dev.h
 unifdef-y += icmp.h
 unifdef-y += icmpv6.h
 unifdef-y += if_addr.h
-unifdef-y += if_addrlabel.h
 unifdef-y += if_arp.h
 unifdef-y += if_bridge.h
 unifdef-y += if_ec.h
@@ -243,7 +243,6 @@ unifdef-y += ipc.h
 unifdef-y += ipmi.h
 unifdef-y += ipv6.h
 unifdef-y += ipv6_route.h
-unifdef-y += ip6_tunnel.h
 unifdef-y += isdn.h
 unifdef-y += isdnif.h
 unifdef-y += isdn_divertif.h
index 2c7e003356ac184f4d7848b44a98468df65e01ec..41f7ce7edd7aea559be60998d65e68569d7b8d45 100644 (file)
@@ -79,6 +79,7 @@ typedef int (*acpi_table_handler) (struct acpi_table_header *table);
 typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end);
 
 char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
+int early_acpi_boot_init(void);
 int acpi_boot_init (void);
 int acpi_boot_table_init (void);
 int acpi_numa_init (void);
@@ -235,6 +236,10 @@ int acpi_check_mem_region(resource_size_t start, resource_size_t n,
 
 #else  /* CONFIG_ACPI */
 
+static inline int early_acpi_boot_init(void)
+{
+       return 0;
+}
 static inline int acpi_boot_init(void)
 {
        return 0;
index 03e34547d489132632b6a15b2286c7dc2ac8ffa5..661d90d6cf7cc848158004c431a19f1365e6f15c 100644 (file)
@@ -30,8 +30,6 @@
 #ifndef _AGP_BACKEND_H
 #define _AGP_BACKEND_H 1
 
-#ifdef __KERNEL__
-
 #ifndef TRUE
 #define TRUE 1
 #endif
@@ -111,5 +109,4 @@ extern struct agp_bridge_data *agp_backend_acquire(struct pci_dev *);
 extern void agp_backend_release(struct agp_bridge_data *);
 extern void agp_flush_chipset(struct agp_bridge_data *);
 
-#endif                         /* __KERNEL__ */
 #endif                         /* _AGP_BACKEND_H */
index 0d0b7f629bd31f9b57154af39085b452e8174847..b51ddd28444e38763e7066ed36ffa9a3a2b6b355 100644 (file)
@@ -209,27 +209,8 @@ extern ssize_t wait_on_sync_kiocb(struct kiocb *iocb);
 extern int aio_put_req(struct kiocb *iocb);
 extern void kick_iocb(struct kiocb *iocb);
 extern int aio_complete(struct kiocb *iocb, long res, long res2);
-extern void __put_ioctx(struct kioctx *ctx);
 struct mm_struct;
 extern void exit_aio(struct mm_struct *mm);
-extern struct kioctx *lookup_ioctx(unsigned long ctx_id);
-extern int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
-                        struct iocb *iocb);
-
-/* semi private, but used by the 32bit emulations: */
-struct kioctx *lookup_ioctx(unsigned long ctx_id);
-int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
-                 struct iocb *iocb);
-
-#define get_ioctx(kioctx) do {                                         \
-       BUG_ON(atomic_read(&(kioctx)->users) <= 0);                     \
-       atomic_inc(&(kioctx)->users);                                   \
-} while (0)
-#define put_ioctx(kioctx) do {                                         \
-       BUG_ON(atomic_read(&(kioctx)->users) <= 0);                     \
-       if (unlikely(atomic_dec_and_test(&(kioctx)->users)))            \
-               __put_ioctx(kioctx);                                    \
-} while (0)
 
 #define io_wait_to_kiocb(wait) container_of(wait, struct kiocb, ki_wait)
 
index 4ccb048cae1de97e0b4c9627f60c1f8cd7894f48..63c3bb98558f6b3e2d07cd9040621273966c1eec 100644 (file)
 /* Rule structure sizes -- if these change, different AUDIT_ADD and
  * AUDIT_LIST commands must be implemented. */
 #define AUDIT_MAX_FIELDS   64
-#define AUDIT_MAX_KEY_LEN  32
+#define AUDIT_MAX_KEY_LEN  256
 #define AUDIT_BITMASK_SIZE 64
 #define AUDIT_WORD(nr) ((__u32)((nr)/32))
 #define AUDIT_BIT(nr)  (1 << ((nr) - AUDIT_WORD(nr)*32))
 #define AUDIT_WATCH    105
 #define AUDIT_PERM     106
 #define AUDIT_DIR      107
+#define AUDIT_FILETYPE 108
 
 #define AUDIT_ARG0      200
 #define AUDIT_ARG1      (AUDIT_ARG0+1)
@@ -549,16 +550,20 @@ extern void                   audit_log_format(struct audit_buffer *ab,
                                             const char *fmt, ...)
                            __attribute__((format(printf,2,3)));
 extern void                audit_log_end(struct audit_buffer *ab);
-extern void                audit_log_hex(struct audit_buffer *ab,
-                                         const unsigned char *buf,
-                                         size_t len);
 extern int                 audit_string_contains_control(const char *string,
                                                          size_t len);
+extern void                audit_log_n_hex(struct audit_buffer *ab,
+                                         const unsigned char *buf,
+                                         size_t len);
+extern void                audit_log_n_string(struct audit_buffer *ab,
+                                              const char *buf,
+                                              size_t n);
+#define audit_log_string(a,b) audit_log_n_string(a, b, strlen(b));
+extern void                audit_log_n_untrustedstring(struct audit_buffer *ab,
+                                                       const char *string,
+                                                       size_t n);
 extern void                audit_log_untrustedstring(struct audit_buffer *ab,
                                                      const char *string);
-extern void                audit_log_n_untrustedstring(struct audit_buffer *ab,
-                                                       size_t n,
-                                                       const char *string);
 extern void                audit_log_d_path(struct audit_buffer *ab,
                                             const char *prefix,
                                             struct path *path);
@@ -569,7 +574,8 @@ extern int              audit_update_lsm_rules(void);
 extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
 extern int audit_filter_type(int type);
 extern int  audit_receive_filter(int type, int pid, int uid, int seq,
-                        void *data, size_t datasz, uid_t loginuid, u32 sid);
+                               void *data, size_t datasz, uid_t loginuid,
+                               u32 sessionid, u32 sid);
 extern int audit_enabled;
 #else
 #define audit_log(c,g,t,f,...) do { ; } while (0)
@@ -577,9 +583,11 @@ extern int audit_enabled;
 #define audit_log_vformat(b,f,a) do { ; } while (0)
 #define audit_log_format(b,f,...) do { ; } while (0)
 #define audit_log_end(b) do { ; } while (0)
-#define audit_log_hex(a,b,l) do { ; } while (0)
-#define audit_log_untrustedstring(a,s) do { ; } while (0)
+#define audit_log_n_hex(a,b,l) do { ; } while (0)
+#define audit_log_n_string(a,c,l) do { ; } while (0)
+#define audit_log_string(a,c) do { ; } while (0)
 #define audit_log_n_untrustedstring(a,n,s) do { ; } while (0)
+#define audit_log_untrustedstring(a,s) do { ; } while (0)
 #define audit_log_d_path(b, p, d) do { ; } while (0)
 #define audit_enabled 0
 #endif
index 48a62baace582a5a841436ba2c8fa1bffdd52c4f..0a24d5550eb3a082725a150856af3055b77f4ae2 100644 (file)
 #include <linux/percpu_counter.h>
 #include <linux/log2.h>
 #include <linux/proportions.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
 #include <asm/atomic.h>
 
 struct page;
+struct device;
+struct dentry;
 
 /*
  * Bits in backing_dev_info.state
@@ -48,11 +52,26 @@ struct backing_dev_info {
 
        struct prop_local_percpu completions;
        int dirty_exceeded;
+
+       unsigned int min_ratio;
+       unsigned int max_ratio, max_prop_frac;
+
+       struct device *dev;
+
+#ifdef CONFIG_DEBUG_FS
+       struct dentry *debug_dir;
+       struct dentry *debug_stats;
+#endif
 };
 
 int bdi_init(struct backing_dev_info *bdi);
 void bdi_destroy(struct backing_dev_info *bdi);
 
+int bdi_register(struct backing_dev_info *bdi, struct device *parent,
+               const char *fmt, ...);
+int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev);
+void bdi_unregister(struct backing_dev_info *bdi);
+
 static inline void __add_bdi_stat(struct backing_dev_info *bdi,
                enum bdi_stat_item item, s64 amount)
 {
@@ -116,6 +135,8 @@ static inline s64 bdi_stat_sum(struct backing_dev_info *bdi,
        return sum;
 }
 
+extern void bdi_writeout_inc(struct backing_dev_info *bdi);
+
 /*
  * maximal error of a stat counter.
  */
@@ -128,24 +149,48 @@ static inline unsigned long bdi_stat_error(struct backing_dev_info *bdi)
 #endif
 }
 
+int bdi_set_min_ratio(struct backing_dev_info *bdi, unsigned int min_ratio);
+int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned int max_ratio);
+
 /*
  * Flags in backing_dev_info::capability
- * - The first two flags control whether dirty pages will contribute to the
- *   VM's accounting and whether writepages() should be called for dirty pages
- *   (something that would not, for example, be appropriate for ramfs)
- * - These flags let !MMU mmap() govern direct device mapping vs immediate
- *   copying more easily for MAP_PRIVATE, especially for ROM filesystems
+ *
+ * The first three flags control whether dirty pages will contribute to the
+ * VM's accounting and whether writepages() should be called for dirty pages
+ * (something that would not, for example, be appropriate for ramfs)
+ *
+ * WARNING: these flags are closely related and should not normally be
+ * used separately.  The BDI_CAP_NO_ACCT_AND_WRITEBACK combines these
+ * three flags into a single convenience macro.
+ *
+ * BDI_CAP_NO_ACCT_DIRTY:  Dirty pages shouldn't contribute to accounting
+ * BDI_CAP_NO_WRITEBACK:   Don't write pages back
+ * BDI_CAP_NO_ACCT_WB:     Don't automatically account writeback pages
+ *
+ * These flags let !MMU mmap() govern direct device mapping vs immediate
+ * copying more easily for MAP_PRIVATE, especially for ROM filesystems.
+ *
+ * BDI_CAP_MAP_COPY:       Copy can be mapped (MAP_PRIVATE)
+ * BDI_CAP_MAP_DIRECT:     Can be mapped directly (MAP_SHARED)
+ * BDI_CAP_READ_MAP:       Can be mapped for reading
+ * BDI_CAP_WRITE_MAP:      Can be mapped for writing
+ * BDI_CAP_EXEC_MAP:       Can be mapped for execution
  */
-#define BDI_CAP_NO_ACCT_DIRTY  0x00000001      /* Dirty pages shouldn't contribute to accounting */
-#define BDI_CAP_NO_WRITEBACK   0x00000002      /* Don't write pages back */
-#define BDI_CAP_MAP_COPY       0x00000004      /* Copy can be mapped (MAP_PRIVATE) */
-#define BDI_CAP_MAP_DIRECT     0x00000008      /* Can be mapped directly (MAP_SHARED) */
-#define BDI_CAP_READ_MAP       0x00000010      /* Can be mapped for reading */
-#define BDI_CAP_WRITE_MAP      0x00000020      /* Can be mapped for writing */
-#define BDI_CAP_EXEC_MAP       0x00000040      /* Can be mapped for execution */
+#define BDI_CAP_NO_ACCT_DIRTY  0x00000001
+#define BDI_CAP_NO_WRITEBACK   0x00000002
+#define BDI_CAP_MAP_COPY       0x00000004
+#define BDI_CAP_MAP_DIRECT     0x00000008
+#define BDI_CAP_READ_MAP       0x00000010
+#define BDI_CAP_WRITE_MAP      0x00000020
+#define BDI_CAP_EXEC_MAP       0x00000040
+#define BDI_CAP_NO_ACCT_WB     0x00000080
+
 #define BDI_CAP_VMFLAGS \
        (BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP)
 
+#define BDI_CAP_NO_ACCT_AND_WRITEBACK \
+       (BDI_CAP_NO_WRITEBACK | BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_ACCT_WB)
+
 #if defined(VM_MAYREAD) && \
        (BDI_CAP_READ_MAP != VM_MAYREAD || \
         BDI_CAP_WRITE_MAP != VM_MAYWRITE || \
@@ -156,9 +201,7 @@ static inline unsigned long bdi_stat_error(struct backing_dev_info *bdi)
 extern struct backing_dev_info default_backing_dev_info;
 void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page);
 
-int writeback_acquire(struct backing_dev_info *bdi);
 int writeback_in_progress(struct backing_dev_info *bdi);
-void writeback_release(struct backing_dev_info *bdi);
 
 static inline int bdi_congested(struct backing_dev_info *bdi, int bdi_bits)
 {
@@ -187,17 +230,32 @@ void clear_bdi_congested(struct backing_dev_info *bdi, int rw);
 void set_bdi_congested(struct backing_dev_info *bdi, int rw);
 long congestion_wait(int rw, long timeout);
 
-#define bdi_cap_writeback_dirty(bdi) \
-       (!((bdi)->capabilities & BDI_CAP_NO_WRITEBACK))
 
-#define bdi_cap_account_dirty(bdi) \
-       (!((bdi)->capabilities & BDI_CAP_NO_ACCT_DIRTY))
+static inline bool bdi_cap_writeback_dirty(struct backing_dev_info *bdi)
+{
+       return !(bdi->capabilities & BDI_CAP_NO_WRITEBACK);
+}
+
+static inline bool bdi_cap_account_dirty(struct backing_dev_info *bdi)
+{
+       return !(bdi->capabilities & BDI_CAP_NO_ACCT_DIRTY);
+}
 
-#define mapping_cap_writeback_dirty(mapping) \
-       bdi_cap_writeback_dirty((mapping)->backing_dev_info)
+static inline bool bdi_cap_account_writeback(struct backing_dev_info *bdi)
+{
+       /* Paranoia: BDI_CAP_NO_WRITEBACK implies BDI_CAP_NO_ACCT_WB */
+       return !(bdi->capabilities & (BDI_CAP_NO_ACCT_WB |
+                                     BDI_CAP_NO_WRITEBACK));
+}
 
-#define mapping_cap_account_dirty(mapping) \
-       bdi_cap_account_dirty((mapping)->backing_dev_info)
+static inline bool mapping_cap_writeback_dirty(struct address_space *mapping)
+{
+       return bdi_cap_writeback_dirty(mapping->backing_dev_info);
+}
 
+static inline bool mapping_cap_account_dirty(struct address_space *mapping)
+{
+       return bdi_cap_account_dirty(mapping->backing_dev_info);
+}
 
 #endif         /* _LINUX_BACKING_DEV_H */
index b7fc55ec8d480d71dcda61a249962ce846f2f22d..b512e48f6d8e9ccbcc811c364cf73a8f85bdd58f 100644 (file)
@@ -34,7 +34,8 @@ struct linux_binprm{
 #endif
        struct mm_struct *mm;
        unsigned long p; /* current top of mem */
-       int sh_bang;
+       unsigned int sh_bang:1,
+                    misc_bang:1;
        struct file * file;
        int e_uid, e_gid;
        kernel_cap_t cap_inheritable, cap_permitted;
@@ -48,7 +49,6 @@ struct linux_binprm{
        unsigned interp_flags;
        unsigned interp_data;
        unsigned long loader, exec;
-       unsigned long argv_len;
 };
 
 #define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0
index d259690863fb0494a5d1ceeb580f30d0ac793eef..61c15eaf3fb3d8f309cd604380f0574f9547749f 100644 (file)
@@ -324,6 +324,8 @@ extern struct bio *bio_map_user_iov(struct request_queue *,
 extern void bio_unmap_user(struct bio *);
 extern struct bio *bio_map_kern(struct request_queue *, void *, unsigned int,
                                gfp_t);
+extern struct bio *bio_copy_kern(struct request_queue *, void *, unsigned int,
+                                gfp_t, int);
 extern void bio_set_pages_dirty(struct bio *bio);
 extern void bio_check_pages_dirty(struct bio *bio);
 extern struct bio *bio_copy_user(struct request_queue *, unsigned long, unsigned int, int);
index 48bde600a2dbcf652715d0c97b4da756ceffad3d..024f2b027244aa8fd8ce35cb4aaa6ee1c9e57fbb 100644 (file)
@@ -6,8 +6,8 @@
 #define BIT(nr)                        (1UL << (nr))
 #define BIT_MASK(nr)           (1UL << ((nr) % BITS_PER_LONG))
 #define BIT_WORD(nr)           ((nr) / BITS_PER_LONG)
-#define BITS_TO_LONGS(nr)      DIV_ROUND_UP(nr, BITS_PER_LONG)
 #define BITS_PER_BYTE          8
+#define BITS_TO_LONGS(nr)      DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
 #endif
 
 /*
@@ -114,8 +114,6 @@ static inline unsigned fls_long(unsigned long l)
 
 #ifdef __KERNEL__
 #ifdef CONFIG_GENERIC_FIND_FIRST_BIT
-extern unsigned long __find_first_bit(const unsigned long *addr,
-               unsigned long size);
 
 /**
  * find_first_bit - find the first set bit in a memory region
@@ -124,28 +122,8 @@ extern unsigned long __find_first_bit(const unsigned long *addr,
  *
  * Returns the bit number of the first set bit.
  */
-static __always_inline unsigned long
-find_first_bit(const unsigned long *addr, unsigned long size)
-{
-       /* Avoid a function call if the bitmap size is a constant */
-       /* and not bigger than BITS_PER_LONG. */
-
-       /* insert a sentinel so that __ffs returns size if there */
-       /* are no set bits in the bitmap */
-       if (__builtin_constant_p(size) && (size < BITS_PER_LONG))
-               return __ffs((*addr) | (1ul << size));
-
-       /* the result of __ffs(0) is undefined, so it needs to be */
-       /* handled separately */
-       if (__builtin_constant_p(size) && (size == BITS_PER_LONG))
-               return ((*addr) == 0) ? BITS_PER_LONG : __ffs(*addr);
-
-       /* size is not constant or too big */
-       return __find_first_bit(addr, size);
-}
-
-extern unsigned long __find_first_zero_bit(const unsigned long *addr,
-               unsigned long size);
+extern unsigned long find_first_bit(const unsigned long *addr,
+                                   unsigned long size);
 
 /**
  * find_first_zero_bit - find the first cleared bit in a memory region
@@ -154,31 +132,12 @@ extern unsigned long __find_first_zero_bit(const unsigned long *addr,
  *
  * Returns the bit number of the first cleared bit.
  */
-static __always_inline unsigned long
-find_first_zero_bit(const unsigned long *addr, unsigned long size)
-{
-       /* Avoid a function call if the bitmap size is a constant */
-       /* and not bigger than BITS_PER_LONG. */
-
-       /* insert a sentinel so that __ffs returns size if there */
-       /* are no set bits in the bitmap */
-       if (__builtin_constant_p(size) && (size < BITS_PER_LONG)) {
-               return __ffs(~(*addr) | (1ul << size));
-       }
-
-       /* the result of __ffs(0) is undefined, so it needs to be */
-       /* handled separately */
-       if (__builtin_constant_p(size) && (size == BITS_PER_LONG))
-               return (~(*addr) == 0) ? BITS_PER_LONG : __ffs(~(*addr));
-
-       /* size is not constant or too big */
-       return __find_first_zero_bit(addr, size);
-}
+extern unsigned long find_first_zero_bit(const unsigned long *addr,
+                                        unsigned long size);
+
 #endif /* CONFIG_GENERIC_FIND_FIRST_BIT */
 
 #ifdef CONFIG_GENERIC_FIND_NEXT_BIT
-extern unsigned long __find_next_bit(const unsigned long *addr,
-               unsigned long size, unsigned long offset);
 
 /**
  * find_next_bit - find the next set bit in a memory region
@@ -186,36 +145,8 @@ extern unsigned long __find_next_bit(const unsigned long *addr,
  * @offset: The bitnumber to start searching at
  * @size: The bitmap size in bits
  */
-static __always_inline unsigned long
-find_next_bit(const unsigned long *addr, unsigned long size,
-               unsigned long offset)
-{
-       unsigned long value;
-
-       /* Avoid a function call if the bitmap size is a constant */
-       /* and not bigger than BITS_PER_LONG. */
-
-       /* insert a sentinel so that __ffs returns size if there */
-       /* are no set bits in the bitmap */
-       if (__builtin_constant_p(size) && (size < BITS_PER_LONG)) {
-               value = (*addr) & ((~0ul) << offset);
-               value |= (1ul << size);
-               return __ffs(value);
-       }
-
-       /* the result of __ffs(0) is undefined, so it needs to be */
-       /* handled separately */
-       if (__builtin_constant_p(size) && (size == BITS_PER_LONG)) {
-               value = (*addr) & ((~0ul) << offset);
-               return (value == 0) ? BITS_PER_LONG : __ffs(value);
-       }
-
-       /* size is not constant or too big */
-       return __find_next_bit(addr, size, offset);
-}
-
-extern unsigned long __find_next_zero_bit(const unsigned long *addr,
-               unsigned long size, unsigned long offset);
+extern unsigned long find_next_bit(const unsigned long *addr,
+                                  unsigned long size, unsigned long offset);
 
 /**
  * find_next_zero_bit - find the next cleared bit in a memory region
@@ -223,33 +154,11 @@ extern unsigned long __find_next_zero_bit(const unsigned long *addr,
  * @offset: The bitnumber to start searching at
  * @size: The bitmap size in bits
  */
-static __always_inline unsigned long
-find_next_zero_bit(const unsigned long *addr, unsigned long size,
-               unsigned long offset)
-{
-       unsigned long value;
-
-       /* Avoid a function call if the bitmap size is a constant */
-       /* and not bigger than BITS_PER_LONG. */
-
-       /* insert a sentinel so that __ffs returns size if there */
-       /* are no set bits in the bitmap */
-       if (__builtin_constant_p(size) && (size < BITS_PER_LONG)) {
-               value = (~(*addr)) & ((~0ul) << offset);
-               value |= (1ul << size);
-               return __ffs(value);
-       }
-
-       /* the result of __ffs(0) is undefined, so it needs to be */
-       /* handled separately */
-       if (__builtin_constant_p(size) && (size == BITS_PER_LONG)) {
-               value = (~(*addr)) & ((~0ul) << offset);
-               return (value == 0) ? BITS_PER_LONG : __ffs(value);
-       }
-
-       /* size is not constant or too big */
-       return __find_next_zero_bit(addr, size, offset);
-}
+
+extern unsigned long find_next_zero_bit(const unsigned long *addr,
+                                       unsigned long size,
+                                       unsigned long offset);
+
 #endif /* CONFIG_GENERIC_FIND_NEXT_BIT */
 #endif /* __KERNEL__ */
 #endif
index c5065e3d2ca9eea3e1a4319d117cdf4d5abbd539..d2a1b71e93c3eee9570e86513bdb2786d260699c 100644 (file)
@@ -215,8 +215,9 @@ struct request {
        /*
         * when request is used as a packet command carrier
         */
-       unsigned int cmd_len;
-       unsigned char cmd[BLK_MAX_CDB];
+       unsigned short cmd_len;
+       unsigned char __cmd[BLK_MAX_CDB];
+       unsigned char *cmd;
 
        unsigned int data_len;
        unsigned int extra_len; /* length of alignment and padding */
@@ -407,6 +408,41 @@ struct request_queue
 #define QUEUE_FLAG_PLUGGED     7       /* queue is plugged */
 #define QUEUE_FLAG_ELVSWITCH   8       /* don't use elevator, just do FIFO */
 #define QUEUE_FLAG_BIDI                9       /* queue supports bidi requests */
+#define QUEUE_FLAG_NOMERGES    10      /* disable merge attempts */
+
+static inline int queue_is_locked(struct request_queue *q)
+{
+#ifdef CONFIG_SMP
+       spinlock_t *lock = q->queue_lock;
+       return lock && spin_is_locked(lock);
+#else
+       return 1;
+#endif
+}
+
+static inline void queue_flag_set_unlocked(unsigned int flag,
+                                          struct request_queue *q)
+{
+       __set_bit(flag, &q->queue_flags);
+}
+
+static inline void queue_flag_set(unsigned int flag, struct request_queue *q)
+{
+       WARN_ON_ONCE(!queue_is_locked(q));
+       __set_bit(flag, &q->queue_flags);
+}
+
+static inline void queue_flag_clear_unlocked(unsigned int flag,
+                                            struct request_queue *q)
+{
+       __clear_bit(flag, &q->queue_flags);
+}
+
+static inline void queue_flag_clear(unsigned int flag, struct request_queue *q)
+{
+       WARN_ON_ONCE(!queue_is_locked(q));
+       __clear_bit(flag, &q->queue_flags);
+}
 
 enum {
        /*
@@ -451,6 +487,7 @@ enum {
 #define blk_queue_plugged(q)   test_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags)
 #define blk_queue_tagged(q)    test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags)
 #define blk_queue_stopped(q)   test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags)
+#define blk_queue_nomerges(q)  test_bit(QUEUE_FLAG_NOMERGES, &(q)->queue_flags)
 #define blk_queue_flushing(q)  ((q)->ordseq)
 
 #define blk_fs_request(rq)     ((rq)->cmd_type == REQ_TYPE_FS)
@@ -496,17 +533,17 @@ static inline int blk_queue_full(struct request_queue *q, int rw)
 static inline void blk_set_queue_full(struct request_queue *q, int rw)
 {
        if (rw == READ)
-               set_bit(QUEUE_FLAG_READFULL, &q->queue_flags);
+               queue_flag_set(QUEUE_FLAG_READFULL, q);
        else
-               set_bit(QUEUE_FLAG_WRITEFULL, &q->queue_flags);
+               queue_flag_set(QUEUE_FLAG_WRITEFULL, q);
 }
 
 static inline void blk_clear_queue_full(struct request_queue *q, int rw)
 {
        if (rw == READ)
-               clear_bit(QUEUE_FLAG_READFULL, &q->queue_flags);
+               queue_flag_clear(QUEUE_FLAG_READFULL, q);
        else
-               clear_bit(QUEUE_FLAG_WRITEFULL, &q->queue_flags);
+               queue_flag_clear(QUEUE_FLAG_WRITEFULL, q);
 }
 
 
@@ -583,6 +620,7 @@ extern int blk_register_queue(struct gendisk *disk);
 extern void blk_unregister_queue(struct gendisk *disk);
 extern void register_disk(struct gendisk *dev);
 extern void generic_make_request(struct bio *bio);
+extern void blk_rq_init(struct request_queue *q, struct request *rq);
 extern void blk_put_request(struct request *);
 extern void __blk_put_request(struct request_queue *, struct request *);
 extern void blk_end_sync_rq(struct request *rq, int error);
@@ -626,6 +664,7 @@ extern void blk_start_queue(struct request_queue *q);
 extern void blk_stop_queue(struct request_queue *q);
 extern void blk_sync_queue(struct request_queue *q);
 extern void __blk_stop_queue(struct request_queue *q);
+extern void __blk_run_queue(struct request_queue *);
 extern void blk_run_queue(struct request_queue *);
 extern void blk_start_queueing(struct request_queue *);
 extern int blk_rq_map_user(struct request_queue *, struct request *, void __user *, unsigned long);
index 932eb02a2753544706983630b58006d4aafa761c..82aa36c53ea7a38e413a384a646f241ef1ebaf1c 100644 (file)
@@ -225,7 +225,6 @@ int block_page_mkwrite(struct vm_area_struct *vma, struct page *page,
                                get_block_t get_block);
 void block_sync_page(struct page *);
 sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *);
-int generic_commit_write(struct file *, struct page *, unsigned, unsigned);
 int block_truncate_page(struct address_space *, loff_t, get_block_t *);
 int file_fsync(struct file *, struct dentry *, int);
 int nobh_write_begin(struct file *, struct address_space *,
index 79bedddfd9ca15c02d9fa91793d24027fa5f6b8c..1133d5f9d8181c4811362c6992b29b157a0dbb4e 100644 (file)
@@ -1,5 +1,3 @@
-header-y += big_endian.h
-header-y += little_endian.h
-
-unifdef-y += generic.h
+unifdef-y += big_endian.h
+unifdef-y += little_endian.h
 unifdef-y += swab.h
index bef87891cb2405941c7f4b4509e4b0f10461b984..961ed4b48d8eba1b7d72628cec0f65be7cacde32 100644 (file)
@@ -101,6 +101,8 @@ static inline __u16 __be16_to_cpup(const __be16 *p)
 #define __cpu_to_be16s(x) do {} while (0)
 #define __be16_to_cpus(x) do {} while (0)
 
+#ifdef __KERNEL__
 #include <linux/byteorder/generic.h>
+#endif
 
 #endif /* _LINUX_BYTEORDER_BIG_ENDIAN_H */
index d3771551fdd9046108596ccc185c431062cb8c01..0846e6b931cefc9ea9baedfe9bfc93300e4c474b 100644 (file)
  *
  */
 
-
-#if defined(__KERNEL__)
-/*
- * inside the kernel, we can use nicknames;
- * outside of it, we must avoid POSIX namespace pollution...
- */
 #define cpu_to_le64 __cpu_to_le64
 #define le64_to_cpu __le64_to_cpu
 #define cpu_to_le32 __cpu_to_le32
@@ -176,6 +170,4 @@ static inline void be64_add_cpu(__be64 *var, u64 val)
        *var = cpu_to_be64(be64_to_cpu(*var) + val);
 }
 
-#endif /* KERNEL */
-
 #endif /* _LINUX_BYTEORDER_GENERIC_H */
index 86e62b7501769fa14e8e6029265edcc694f5a692..05dc7c35b3b21e93956f5c462f24a79305749aed 100644 (file)
@@ -101,6 +101,8 @@ static inline __u16 __be16_to_cpup(const __be16 *p)
 #define __cpu_to_be16s(x) __swab16s((x))
 #define __be16_to_cpus(x) __swab16s((x))
 
+#ifdef __KERNEL__
 #include <linux/byteorder/generic.h>
+#endif
 
 #endif /* _LINUX_BYTEORDER_LITTLE_ENDIAN_H */
index eaab759b14603098bfd2a2794b4d63c3185e51e5..f4ea0dd9a618c737228cffd9fba1a52eea2fca64 100644 (file)
@@ -365,12 +365,12 @@ typedef struct kernel_cap_struct {
 # error Fix up hand-coded capability macro initializers
 #else /* HAND-CODED capability initializers */
 
-# define CAP_EMPTY_SET    {{ 0, 0 }}
-# define CAP_FULL_SET     {{ ~0, ~0 }}
-# define CAP_INIT_EFF_SET {{ ~CAP_TO_MASK(CAP_SETPCAP), ~0 }}
-# define CAP_FS_SET       {{ CAP_FS_MASK_B0, CAP_FS_MASK_B1 } }
-# define CAP_NFSD_SET     {{ CAP_FS_MASK_B0|CAP_TO_MASK(CAP_SYS_RESOURCE), \
-                            CAP_FS_MASK_B1 } }
+# define CAP_EMPTY_SET    ((kernel_cap_t){{ 0, 0 }})
+# define CAP_FULL_SET     ((kernel_cap_t){{ ~0, ~0 }})
+# define CAP_INIT_EFF_SET ((kernel_cap_t){{ ~CAP_TO_MASK(CAP_SETPCAP), ~0 }})
+# define CAP_FS_SET       ((kernel_cap_t){{ CAP_FS_MASK_B0, CAP_FS_MASK_B1 } })
+# define CAP_NFSD_SET     ((kernel_cap_t){{ CAP_FS_MASK_B0|CAP_TO_MASK(CAP_SYS_RESOURCE), \
+                                       CAP_FS_MASK_B1 } })
 
 #endif /* _LINUX_CAPABILITY_U32S != 2 */
 
index 1e29b13d00621ee32fcb50f1e08b4dd93b62afcd..fb4591977b039a80587fa79d899c2f86d632657b 100644 (file)
@@ -1,6 +1,5 @@
 #ifndef _LINUX_CDEV_H
 #define _LINUX_CDEV_H
-#ifdef __KERNEL__
 
 #include <linux/kobject.h>
 #include <linux/kdev_t.h>
@@ -34,4 +33,3 @@ void cd_forget(struct inode *);
 extern struct backing_dev_info directly_mappable_cdev_bdi;
 
 #endif
-#endif
index a6a6035a4e1ec16d1e27a3f2470fc316c476cd6a..e155aa78d8594eb545547f48f47c7b53bf9fc36a 100644 (file)
@@ -88,6 +88,17 @@ static inline void css_put(struct cgroup_subsys_state *css)
                __css_put(css);
 }
 
+/* bits in struct cgroup flags field */
+enum {
+       /* Control Group is dead */
+       CGRP_REMOVED,
+       /* Control Group has previously had a child cgroup or a task,
+        * but no longer (only if CGRP_NOTIFY_ON_RELEASE is set) */
+       CGRP_RELEASABLE,
+       /* Control Group requires release notifications to userspace */
+       CGRP_NOTIFY_ON_RELEASE,
+};
+
 struct cgroup {
        unsigned long flags;            /* "unsigned long" so bitops work */
 
@@ -139,10 +150,10 @@ struct css_set {
        struct kref ref;
 
        /*
-        * List running through all cgroup groups. Protected by
-        * css_set_lock
+        * List running through all cgroup groups in the same hash
+        * slot. Protected by css_set_lock
         */
-       struct list_head list;
+       struct hlist_node hlist;
 
        /*
         * List running through all tasks using this cgroup
@@ -163,7 +174,16 @@ struct css_set {
         * during subsystem registration (at boot time).
         */
        struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
+};
+
+/*
+ * cgroup_map_cb is an abstract callback API for reporting map-valued
+ * control files
+ */
 
+struct cgroup_map_cb {
+       int (*fill)(struct cgroup_map_cb *cb, const char *key, u64 value);
+       void *state;
 };
 
 /* struct cftype:
@@ -190,20 +210,51 @@ struct cftype {
                         struct file *file,
                         char __user *buf, size_t nbytes, loff_t *ppos);
        /*
-        * read_uint() is a shortcut for the common case of returning a
+        * read_u64() is a shortcut for the common case of returning a
         * single integer. Use it in place of read()
         */
-       u64 (*read_uint) (struct cgroup *cgrp, struct cftype *cft);
+       u64 (*read_u64) (struct cgroup *cgrp, struct cftype *cft);
+       /*
+        * read_s64() is a signed version of read_u64()
+        */
+       s64 (*read_s64) (struct cgroup *cgrp, struct cftype *cft);
+       /*
+        * read_map() is used for defining a map of key/value
+        * pairs. It should call cb->fill(cb, key, value) for each
+        * entry. The key/value pairs (and their ordering) should not
+        * change between reboots.
+        */
+       int (*read_map) (struct cgroup *cont, struct cftype *cft,
+                        struct cgroup_map_cb *cb);
+       /*
+        * read_seq_string() is used for outputting a simple sequence
+        * using seqfile.
+        */
+       int (*read_seq_string) (struct cgroup *cont, struct cftype *cft,
+                        struct seq_file *m);
+
        ssize_t (*write) (struct cgroup *cgrp, struct cftype *cft,
                          struct file *file,
                          const char __user *buf, size_t nbytes, loff_t *ppos);
 
        /*
-        * write_uint() is a shortcut for the common case of accepting
+        * write_u64() is a shortcut for the common case of accepting
         * a single integer (as parsed by simple_strtoull) from
         * userspace. Use in place of write(); return 0 or error.
         */
-       int (*write_uint) (struct cgroup *cgrp, struct cftype *cft, u64 val);
+       int (*write_u64) (struct cgroup *cgrp, struct cftype *cft, u64 val);
+       /*
+        * write_s64() is a signed version of write_u64()
+        */
+       int (*write_s64) (struct cgroup *cgrp, struct cftype *cft, s64 val);
+
+       /*
+        * trigger() callback can be used to get some kick from the
+        * userspace, when the actual string written is not important
+        * at all. The private field can be used to determine the
+        * kick type for multiplexing.
+        */
+       int (*trigger)(struct cgroup *cgrp, unsigned int event);
 
        int (*release) (struct inode *inode, struct file *file);
 };
@@ -254,6 +305,12 @@ struct cgroup_subsys {
                        struct cgroup *cgrp);
        void (*post_clone)(struct cgroup_subsys *ss, struct cgroup *cgrp);
        void (*bind)(struct cgroup_subsys *ss, struct cgroup *root);
+       /*
+        * This routine is called with the task_lock of mm->owner held
+        */
+       void (*mm_owner_changed)(struct cgroup_subsys *ss,
+                                       struct cgroup *old,
+                                       struct cgroup *new);
        int subsys_id;
        int active;
        int disabled;
@@ -339,4 +396,13 @@ static inline int cgroupstats_build(struct cgroupstats *stats,
 
 #endif /* !CONFIG_CGROUPS */
 
+#ifdef CONFIG_MM_OWNER
+extern void
+cgroup_mm_owner_callbacks(struct task_struct *old, struct task_struct *new);
+#else /* !CONFIG_MM_OWNER */
+static inline void
+cgroup_mm_owner_callbacks(struct task_struct *old, struct task_struct *new)
+{
+}
+#endif /* CONFIG_MM_OWNER */
 #endif /* _LINUX_CGROUP_H */
index 1ddebfc52565f3eb4894c422c1fc5dd831ae523c..e2877454ec82df3205c0251f9c9759db9334dedb 100644 (file)
@@ -42,3 +42,9 @@ SUBSYS(mem_cgroup)
 #endif
 
 /* */
+
+#ifdef CONFIG_CGROUP_DEVICE
+SUBSYS(devices)
+#endif
+
+/* */
index 424fe9cf02c4efd833aaf53847ee985b735aa22e..b3ef0c461578c834c1266dc10b0390c51658aae6 100644 (file)
@@ -8,7 +8,6 @@
 #ifndef _LINUX_CODA_FS_I
 #define _LINUX_CODA_FS_I
 
-#ifdef __KERNEL__
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/coda.h>
@@ -52,4 +51,3 @@ struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb);
 void coda_replace_fid(struct inode *, struct CodaFid *, struct CodaFid *);
 
 #endif
-#endif
index 1c47a34aa79442f738bebf25f01756ddaceb586d..31b75311e2ca381bc4d12fef44f577919a7e57a5 100644 (file)
@@ -43,9 +43,6 @@ int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 int coda_setattr(struct dentry *, struct iattr *);
 
 /* this file:  heloers */
-static __inline__ struct CodaFid *coda_i2f(struct inode *);
-static __inline__ char *coda_i2s(struct inode *);
-static __inline__ void coda_flag_inode(struct inode *, int flag);
 char *coda_f2s(struct CodaFid *f);
 int coda_isroot(struct inode *i);
 int coda_iscontrol(const char *name, size_t length);
index 27304651d700ef7048294e4e001a96d099ce356a..977acb3d1fb2ee81534b5906b3817f90455454ac 100644 (file)
@@ -8,7 +8,7 @@
 
 #ifndef _LINUX_CONCAP_H
 #define _LINUX_CONCAP_H
-#ifdef __KERNEL__
+
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 
@@ -110,4 +110,3 @@ extern int concap_nop(struct concap_proto *cprot);
  */
 extern int concap_drop_skb(struct concap_proto *cprot, struct sk_buff *skb);
 #endif
-#endif
index 4b287ad9371abe101956dd2a05015ca7cda7459f..3ae65b1bf90fd891b32538390c103f12632560fd 100644 (file)
@@ -35,8 +35,6 @@
 #ifndef _CONFIGFS_H_
 #define _CONFIGFS_H_
 
-#ifdef __KERNEL__
-
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/list.h>
@@ -194,6 +192,4 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys);
 int configfs_depend_item(struct configfs_subsystem *subsys, struct config_item *target);
 void configfs_undepend_item(struct configfs_subsystem *subsys, struct config_item *target);
 
-#endif  /* __KERNEL__ */
-
 #endif /* _CONFIGFS_H_ */
index a5f88a6a259d84a92e93a905a7937b03b7501dbf..a4f27fbdf5494ee885caa967a24d1934744386a3 100644 (file)
@@ -91,6 +91,7 @@ void give_up_console(const struct consw *sw);
 #define CON_ENABLED    (4)
 #define CON_BOOT       (8)
 #define CON_ANYTIME    (16) /* Safe to call when cpu is offline */
+#define CON_BRL                (32) /* Used for a braille device */
 
 struct console {
        char    name[16];
@@ -121,6 +122,9 @@ extern struct tty_driver *console_device(int *);
 extern void console_stop(struct console *);
 extern void console_start(struct console *);
 extern int is_console_locked(void);
+extern int braille_register_console(struct console *, int index,
+               char *console_options, char *braille_options);
+extern int braille_unregister_console(struct console *);
 
 extern int console_suspend_enabled;
 
index d71f7c0f931b34b63bfacde2b06d19ffc5001616..b03f80a078bee4f8d822dd90fc73545def4adcce 100644 (file)
@@ -53,6 +53,7 @@ struct vc_data {
        unsigned short  vc_hi_font_mask;        /* [#] Attribute set for upper 256 chars of font or 0 if not supported */
        struct console_font vc_font;            /* Current VC font set */
        unsigned short  vc_video_erase_char;    /* Background erase character */
+       unsigned short  vc_scrl_erase_char;     /* Erase character for scroll */
        /* VT terminal data */
        unsigned int    vc_state;               /* Escape sequence parser state */
        unsigned int    vc_npar,vc_par[NPAR];   /* Parameters of current escape sequence */
index f212fa98283e83425ea9db7ee2ba5e3de55e173b..7464ba3b4333980268d4af8e71318a0b27a37e9d 100644 (file)
@@ -108,7 +108,7 @@ static inline void cpuhotplug_mutex_unlock(struct mutex *cpu_hp_mutex)
 extern void get_online_cpus(void);
 extern void put_online_cpus(void);
 #define hotcpu_notifier(fn, pri) {                             \
-       static struct notifier_block fn##_nb =                  \
+       static struct notifier_block fn##_nb __cpuinitdata =    \
                { .notifier_call = fn, .priority = pri };       \
        register_cpu_notifier(&fn##_nb);                        \
 }
index ddd8652fc3f38a91d5f471fd70a534e21337ba12..e7e91dbfde0f25927490cf1c9d18c3587b8d7ea3 100644 (file)
@@ -83,7 +83,8 @@ struct cpufreq_real_policy {
 };
 
 struct cpufreq_policy {
-       cpumask_t               cpus;   /* affected CPUs */
+       cpumask_t               cpus;   /* CPUs requiring sw coordination */
+       cpumask_t               related_cpus; /* CPUs with any coordination */
        unsigned int            shared_type; /* ANY or ALL affected CPUs
                                                should set cpufreq */
        unsigned int            cpu;    /* cpu nr of registered CPU */
@@ -307,6 +308,9 @@ extern struct cpufreq_governor cpufreq_gov_performance;
 #endif
 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE
 #define CPUFREQ_DEFAULT_GOVERNOR       (&cpufreq_gov_performance)
+#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE)
+extern struct cpufreq_governor cpufreq_gov_powersave;
+#define CPUFREQ_DEFAULT_GOVERNOR       (&cpufreq_gov_powersave)
 #elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE)
 extern struct cpufreq_governor cpufreq_gov_userspace;
 #define CPUFREQ_DEFAULT_GOVERNOR       (&cpufreq_gov_userspace)
index 90037617da8fedf515b269d8ed766074f55244d0..f52696a1ff0daa40414af9b071678280a373655a 100644 (file)
@@ -1,6 +1,5 @@
 #ifndef _LINUX_CRC_CCITT_H
 #define _LINUX_CRC_CCITT_H
-#ifdef __KERNEL__
 
 #include <linux/types.h>
 
@@ -13,5 +12,4 @@ static inline u16 crc_ccitt_byte(u16 crc, const u8 c)
        return (crc >> 8) ^ crc_ccitt_table[(crc ^ c) & 0xff];
 }
 
-#endif /* __KERNEL__ */
 #endif /* _LINUX_CRC_CCITT_H */
index cfb1627ac51c88866b506953f4a52f41ff4620c4..2a6639407c8037581ce7baa58e95c8c936a26245 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef __LINUX_DCACHE_H
 #define __LINUX_DCACHE_H
 
-#ifdef __KERNEL__
-
 #include <asm/atomic.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
@@ -365,6 +363,4 @@ extern struct dentry *lookup_create(struct nameidata *nd, int is_dir);
 
 extern int sysctl_vfs_cache_pressure;
 
-#endif /* __KERNEL__ */
-
 #endif /* __LINUX_DCACHE_H */
diff --git a/include/linux/debugobjects.h b/include/linux/debugobjects.h
new file mode 100644 (file)
index 0000000..8c243aa
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef _LINUX_DEBUGOBJECTS_H
+#define _LINUX_DEBUGOBJECTS_H
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
+enum debug_obj_state {
+       ODEBUG_STATE_NONE,
+       ODEBUG_STATE_INIT,
+       ODEBUG_STATE_INACTIVE,
+       ODEBUG_STATE_ACTIVE,
+       ODEBUG_STATE_DESTROYED,
+       ODEBUG_STATE_NOTAVAILABLE,
+       ODEBUG_STATE_MAX,
+};
+
+struct debug_obj_descr;
+
+/**
+ * struct debug_obj - representaion of an tracked object
+ * @node:      hlist node to link the object into the tracker list
+ * @state:     tracked object state
+ * @object:    pointer to the real object
+ * @descr:     pointer to an object type specific debug description structure
+ */
+struct debug_obj {
+       struct hlist_node       node;
+       enum debug_obj_state    state;
+       void                    *object;
+       struct debug_obj_descr  *descr;
+};
+
+/**
+ * struct debug_obj_descr - object type specific debug description structure
+ * @name:              name of the object typee
+ * @fixup_init:                fixup function, which is called when the init check
+ *                     fails
+ * @fixup_activate:    fixup function, which is called when the activate check
+ *                     fails
+ * @fixup_destroy:     fixup function, which is called when the destroy check
+ *                     fails
+ * @fixup_free:                fixup function, which is called when the free check
+ *                     fails
+ */
+struct debug_obj_descr {
+       const char              *name;
+
+       int (*fixup_init)       (void *addr, enum debug_obj_state state);
+       int (*fixup_activate)   (void *addr, enum debug_obj_state state);
+       int (*fixup_destroy)    (void *addr, enum debug_obj_state state);
+       int (*fixup_free)       (void *addr, enum debug_obj_state state);
+};
+
+#ifdef CONFIG_DEBUG_OBJECTS
+extern void debug_object_init      (void *addr, struct debug_obj_descr *descr);
+extern void
+debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr);
+extern void debug_object_activate  (void *addr, struct debug_obj_descr *descr);
+extern void debug_object_deactivate(void *addr, struct debug_obj_descr *descr);
+extern void debug_object_destroy   (void *addr, struct debug_obj_descr *descr);
+extern void debug_object_free      (void *addr, struct debug_obj_descr *descr);
+
+extern void debug_objects_early_init(void);
+extern void debug_objects_mem_init(void);
+#else
+static inline void
+debug_object_init      (void *addr, struct debug_obj_descr *descr) { }
+static inline void
+debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr) { }
+static inline void
+debug_object_activate  (void *addr, struct debug_obj_descr *descr) { }
+static inline void
+debug_object_deactivate(void *addr, struct debug_obj_descr *descr) { }
+static inline void
+debug_object_destroy   (void *addr, struct debug_obj_descr *descr) { }
+static inline void
+debug_object_free      (void *addr, struct debug_obj_descr *descr) { }
+
+static inline void debug_objects_early_init(void) { }
+static inline void debug_objects_mem_init(void) { }
+#endif
+
+#ifdef CONFIG_DEBUG_OBJECTS_FREE
+extern void debug_check_no_obj_freed(const void *address, unsigned long size);
+#else
+static inline void
+debug_check_no_obj_freed(const void *address, unsigned long size) { }
+#endif
+
+#endif
index ad3b787479a49ef54daff54e12f505b2833fd731..0d8d419d191ab1022036efee46bd7074968890e3 100644 (file)
@@ -8,8 +8,6 @@
 #ifndef _LINUX_DEVICE_MAPPER_H
 #define _LINUX_DEVICE_MAPPER_H
 
-#ifdef __KERNEL__
-
 #include <linux/bio.h>
 
 struct dm_target;
@@ -344,5 +342,4 @@ static inline unsigned long to_bytes(sector_t n)
        return (n << SECTOR_SHIFT);
 }
 
-#endif /* __KERNEL__ */
 #endif /* _LINUX_DEVICE_MAPPER_H */
diff --git a/include/linux/device_cgroup.h b/include/linux/device_cgroup.h
new file mode 100644 (file)
index 0000000..0b0d9c3
--- /dev/null
@@ -0,0 +1,12 @@
+#include <linux/module.h>
+#include <linux/fs.h>
+
+#ifdef CONFIG_CGROUP_DEVICE
+extern int devcgroup_inode_permission(struct inode *inode, int mask);
+extern int devcgroup_inode_mknod(int mode, dev_t dev);
+#else
+static inline int devcgroup_inode_permission(struct inode *inode, int mask)
+{ return 0; }
+static inline int devcgroup_inode_mknod(int mode, dev_t dev)
+{ return 0; }
+#endif
index b672ddc007357bc2cd5395d34e6102f6870315a6..154769cad3f31c7207b3113ec5e00753a4684ee2 100644 (file)
@@ -17,6 +17,8 @@
 
 #ifdef CONFIG_UNIX98_PTYS
 
+int devpts_new_index(void);
+void devpts_kill_index(int idx);
 int devpts_pty_new(struct tty_struct *tty);      /* mknod in devpts */
 struct tty_struct *devpts_get_tty(int number);  /* get tty structure */
 void devpts_pty_kill(int number);               /* unlink */
@@ -24,6 +26,8 @@ void devpts_pty_kill(int number);              /* unlink */
 #else
 
 /* Dummy stubs in the no-pty case */
+static inline int devpts_new_index(void) { return -EINVAL; }
+static inline void devpts_kill_index(int idx) { }
 static inline int devpts_pty_new(struct tty_struct *tty) { return -EINVAL; }
 static inline struct tty_struct *devpts_get_tty(int number) { return NULL; }
 static inline void devpts_pty_kill(int number) { }
diff --git a/include/linux/dma-attrs.h b/include/linux/dma-attrs.h
new file mode 100644 (file)
index 0000000..1677e2b
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef _DMA_ATTR_H
+#define _DMA_ATTR_H
+
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/bug.h>
+
+/**
+ * an enum dma_attr represents an attribute associated with a DMA
+ * mapping. The semantics of each attribute should be defined in
+ * Documentation/DMA-attributes.txt.
+ */
+enum dma_attr {
+       DMA_ATTR_WRITE_BARRIER,
+       DMA_ATTR_MAX,
+};
+
+#define __DMA_ATTRS_LONGS BITS_TO_LONGS(DMA_ATTR_MAX)
+
+/**
+ * struct dma_attrs - an opaque container for DMA attributes
+ * @flags - bitmask representing a collection of enum dma_attr
+ */
+struct dma_attrs {
+       unsigned long flags[__DMA_ATTRS_LONGS];
+};
+
+#define DEFINE_DMA_ATTRS(x)                                    \
+       struct dma_attrs x = {                                  \
+               .flags = { [0 ... __DMA_ATTRS_LONGS-1] = 0 },   \
+       }
+
+static inline void init_dma_attrs(struct dma_attrs *attrs)
+{
+       bitmap_zero(attrs->flags, __DMA_ATTRS_LONGS);
+}
+
+#ifdef CONFIG_HAVE_DMA_ATTRS
+/**
+ * dma_set_attr - set a specific attribute
+ * @attr: attribute to set
+ * @attrs: struct dma_attrs (may be NULL)
+ */
+static inline void dma_set_attr(enum dma_attr attr, struct dma_attrs *attrs)
+{
+       if (attrs == NULL)
+               return;
+       BUG_ON(attr >= DMA_ATTR_MAX);
+       __set_bit(attr, attrs->flags);
+}
+
+/**
+ * dma_get_attr - check for a specific attribute
+ * @attr: attribute to set
+ * @attrs: struct dma_attrs (may be NULL)
+ */
+static inline int dma_get_attr(enum dma_attr attr, struct dma_attrs *attrs)
+{
+       if (attrs == NULL)
+               return 0;
+       BUG_ON(attr >= DMA_ATTR_MAX);
+       return test_bit(attr, attrs->flags);
+}
+#else /* !CONFIG_HAVE_DMA_ATTRS */
+static inline void dma_set_attr(enum dma_attr attr, struct dma_attrs *attrs)
+{
+}
+
+static inline int dma_get_attr(enum dma_attr attr, struct dma_attrs *attrs)
+{
+       return 0;
+}
+#endif /* CONFIG_HAVE_DMA_ATTRS */
+#endif /* _DMA_ATTR_H */
index 3320307096237a61495d785d751e897bc54a0102..952e0f857ac9d9545750bbd5f197df6034a99913 100644 (file)
@@ -146,4 +146,21 @@ static inline void dmam_release_declared_memory(struct device *dev)
 }
 #endif /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */
 
+#ifndef CONFIG_HAVE_DMA_ATTRS
+struct dma_attrs;
+
+#define dma_map_single_attrs(dev, cpu_addr, size, dir, attrs) \
+       dma_map_single(dev, cpu_addr, size, dir)
+
+#define dma_unmap_single_attrs(dev, dma_addr, size, dir, attrs) \
+       dma_unmap_single(dev, dma_addr, size, dir)
+
+#define dma_map_sg_attrs(dev, sgl, nents, dir, attrs) \
+       dma_map_sg(dev, sgl, nents, dir)
+
+#define dma_unmap_sg_attrs(dev, sgl, nents, dir, attrs) \
+       dma_unmap_sg(dev, sgl, nents, dir)
+
+#endif /* CONFIG_HAVE_DMA_ATTRS */
+
 #endif
index eab451e69a91a0892fee9fa556b4d3a652bdd056..7cf92e8a4196c0f6a38257cec095b1aa6d04939f 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Author: Dave Jiang <djiang@mvista.com>
  *
- * 2006-2007 (c) MontaVista Software, Inc. This file is licensed under
+ * 2006-2008 (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.
@@ -26,4 +26,16 @@ extern atomic_t edac_handlers;
 extern int edac_handler_set(void);
 extern void edac_atomic_assert_error(void);
 
+static inline void opstate_init(void)
+{
+       switch (edac_op_state) {
+       case EDAC_OPSTATE_POLL:
+       case EDAC_OPSTATE_NMI:
+               break;
+       default:
+               edac_op_state = EDAC_OPSTATE_POLL;
+       }
+       return;
+}
+
 #endif
index bad1b16ec49a73f432ed27a0c97131205f726c29..ff9fbed90123faff8fb8e3a7817a831f6bc5e276 100644 (file)
@@ -208,7 +208,7 @@ typedef struct elf32_hdr{
 } Elf32_Ehdr;
 
 typedef struct elf64_hdr {
-  unsigned char        e_ident[16];            /* ELF "magic number" */
+  unsigned char        e_ident[EI_NIDENT];     /* ELF "magic number" */
   Elf64_Half e_type;
   Elf64_Half e_machine;
   Elf64_Word e_version;
index b489fc6d0b6252f9e75134d8e7ecf5e529c623c5..a701399b7fed915e8cbd057be25a57d32bb2de10 100644 (file)
@@ -8,9 +8,6 @@
 #ifndef _LINUX_EVENTFD_H
 #define _LINUX_EVENTFD_H
 
-
-#ifdef __KERNEL__
-
 #ifdef CONFIG_EVENTFD
 
 struct file *eventfd_fget(int fd);
@@ -24,7 +21,5 @@ static inline int eventfd_signal(struct file *file, int n)
 
 #endif /* CONFIG_EVENTFD */
 
-#endif /* __KERNEL__ */
-
 #endif /* _LINUX_EVENTFD_H */
 
index 2c925747bc494d684deac9355aa3c66083d9e69b..a1ba005d08e7ef80f441d00a7f5d934582fe13e6 100644 (file)
@@ -1521,7 +1521,6 @@ extern int get_sb_pseudo(struct file_system_type *, char *,
        const struct super_operations *ops, unsigned long,
        struct vfsmount *mnt);
 extern int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb);
-int __put_super(struct super_block *sb);
 int __put_super_and_need_restart(struct super_block *sb);
 void unnamed_dev_init(void);
 
@@ -1965,7 +1964,6 @@ extern int vfs_stat_fd(int dfd, char __user *, struct kstat *);
 extern int vfs_lstat_fd(int dfd, char __user *, struct kstat *);
 extern int vfs_fstat(unsigned int, struct kstat *);
 
-extern long vfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
 extern int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
                    unsigned long arg);
 
index 2cad5c67397e661766aaf10c0e77aacc7a8bac5b..c415a496de3a1a08d02ddc6668cf4f49ba98a979 100644 (file)
@@ -14,7 +14,6 @@
  * option) any later version.
  */
 
-#ifdef __KERNEL__
 #ifndef _FSL_DEVICE_H_
 #define _FSL_DEVICE_H_
 
@@ -127,4 +126,3 @@ struct mpc8xx_pcmcia_ops {
 };
 
 #endif /* _FSL_DEVICE_H_ */
-#endif /* __KERNEL__ */
index d4b7c4ac72e6dd70e9bbda61158b36847e83bb2a..a89513188ce7a85c076f11e512d994b0447b384e 100644 (file)
@@ -11,8 +11,6 @@
  * (C) Copyright 2005 Robert Love
  */
 
-#ifdef __KERNEL__
-
 #include <linux/dnotify.h>
 #include <linux/inotify.h>
 #include <linux/audit.h>
@@ -296,6 +294,4 @@ static inline void fsnotify_oldname_free(const char *old_name)
 
 #endif /* ! CONFIG_INOTIFY */
 
-#endif /* __KERNEL__ */
-
 #endif /* _LINUX_FS_NOTIFY_H */
index 5412da28fa4749daa9822bd4b99f82a61628388a..110833666e37a3dc4de25cf698d1057b7c5e56d9 100644 (file)
@@ -78,7 +78,7 @@ struct gs_port {
 #define GS_DEBUG_WRITE   0x00000040
 
 #ifdef __KERNEL__
-void gs_put_char(struct tty_struct *tty, unsigned char ch);
+int gs_put_char(struct tty_struct *tty, unsigned char ch);
 int  gs_write(struct tty_struct *tty, 
              const unsigned char *buf, int count);
 int  gs_write_room(struct tty_struct *tty);
index c37653b6843fb81bdd60f4e07fd54ec3d9e8c3f3..b414be387180f1db79c90977921296640e15f5e9 100644 (file)
@@ -40,9 +40,9 @@ struct vm_area_struct;
 #define __GFP_FS       ((__force gfp_t)0x80u)  /* Can call down to low-level FS? */
 #define __GFP_COLD     ((__force gfp_t)0x100u) /* Cache-cold page required */
 #define __GFP_NOWARN   ((__force gfp_t)0x200u) /* Suppress page allocation failure warning */
-#define __GFP_REPEAT   ((__force gfp_t)0x400u) /* Retry the allocation.  Might fail */
-#define __GFP_NOFAIL   ((__force gfp_t)0x800u) /* Retry for ever.  Cannot fail */
-#define __GFP_NORETRY  ((__force gfp_t)0x1000u)/* Do not retry.  Might fail */
+#define __GFP_REPEAT   ((__force gfp_t)0x400u) /* See above */
+#define __GFP_NOFAIL   ((__force gfp_t)0x800u) /* See above */
+#define __GFP_NORETRY  ((__force gfp_t)0x1000u)/* See above */
 #define __GFP_COMP     ((__force gfp_t)0x4000u)/* Add compound page metadata */
 #define __GFP_ZERO     ((__force gfp_t)0x8000u)/* Return zeroed page on success */
 #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
index 56f3236da829e5d26ca2434b7e7467d99f6c1611..31a4d653389f6d8e76405451c75f88c721328c03 100644 (file)
@@ -266,6 +266,21 @@ extern ktime_t ktime_get_real(void);
 extern void hrtimer_init(struct hrtimer *timer, clockid_t which_clock,
                         enum hrtimer_mode mode);
 
+#ifdef CONFIG_DEBUG_OBJECTS_TIMERS
+extern void hrtimer_init_on_stack(struct hrtimer *timer, clockid_t which_clock,
+                                 enum hrtimer_mode mode);
+
+extern void destroy_hrtimer_on_stack(struct hrtimer *timer);
+#else
+static inline void hrtimer_init_on_stack(struct hrtimer *timer,
+                                        clockid_t which_clock,
+                                        enum hrtimer_mode mode)
+{
+       hrtimer_init(timer, which_clock, mode);
+}
+static inline void destroy_hrtimer_on_stack(struct hrtimer *timer) { }
+#endif
+
 /* Basic timer operations: */
 extern int hrtimer_start(struct hrtimer *timer, ktime_t tim,
                         const enum hrtimer_mode mode);
index 85d11916e9ea48a878f54eb3aff5045a8ec2b2c7..7244456e7e6573466f0534857bef00b8b1dbdad7 100644 (file)
@@ -11,7 +11,6 @@
 
 #ifndef LINUX_HWRANDOM_H_
 #define LINUX_HWRANDOM_H_
-#ifdef __KERNEL__
 
 #include <linux/types.h>
 #include <linux/list.h>
@@ -46,5 +45,4 @@ extern int hwrng_register(struct hwrng *rng);
 /** Unregister a Hardware Random Number Generator driver. */
 extern void hwrng_unregister(struct hwrng *rng);
 
-#endif /* __KERNEL__ */
 #endif /* LINUX_HWRANDOM_H_ */
index 32eb8bbe48317d4acacfcb9719f4ea44f2287d9f..580acc93903e63795a23c1efee2dddbc23cab7b0 100644 (file)
 #define I2C_DRIVERID_UPD64031A 79      /* upd64031a video processor    */
 #define I2C_DRIVERID_SAA717X   80      /* saa717x video encoder        */
 #define I2C_DRIVERID_DS1672    81      /* Dallas/Maxim DS1672 RTC      */
-#define I2C_DRIVERID_X1205     82      /* Xicor/Intersil X1205 RTC     */
-#define I2C_DRIVERID_PCF8563   83      /* Philips PCF8563 RTC          */
 #define I2C_DRIVERID_BT866     85      /* Conexant bt866 video encoder */
 #define I2C_DRIVERID_KS0127    86      /* Samsung ks0127 video decoder */
 #define I2C_DRIVERID_TLV320AIC23B 87   /* TI TLV320AIC23B audio codec  */
-#define I2C_DRIVERID_ISL1208   88      /* Intersil ISL1208 RTC         */
 #define I2C_DRIVERID_WM8731    89      /* Wolfson WM8731 audio codec */
 #define I2C_DRIVERID_WM8750    90      /* Wolfson WM8750 audio codec */
 #define I2C_DRIVERID_WM8753    91      /* Wolfson WM8753 audio codec */
index 365e0df3646baf525d94aaec7899fa93a8f2a05c..cb63da5c2139f04c331f44da7e681c36ec07ece1 100644 (file)
@@ -126,7 +126,7 @@ struct i2c_driver {
         * With the driver model, device enumeration is NEVER done by drivers;
         * it's done by infrastructure.  (NEW STYLE DRIVERS ONLY)
         */
-       int (*probe)(struct i2c_client *);
+       int (*probe)(struct i2c_client *, const struct i2c_device_id *);
        int (*remove)(struct i2c_client *);
 
        /* driver model interfaces that don't relate to enumeration  */
@@ -140,11 +140,10 @@ struct i2c_driver {
        int (*command)(struct i2c_client *client,unsigned int cmd, void *arg);
 
        struct device_driver driver;
+       const struct i2c_device_id *id_table;
 };
 #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
 
-#define I2C_NAME_SIZE  20
-
 /**
  * struct i2c_client - represent an I2C slave device
  * @flags: I2C_CLIENT_TEN indicates the device uses a ten bit chip address;
@@ -230,17 +229,17 @@ struct i2c_board_info {
 };
 
 /**
- * I2C_BOARD_INFO - macro used to list an i2c device and its driver
- * @driver: identifies the driver to use with the device
+ * I2C_BOARD_INFO - macro used to list an i2c device and its address
+ * @dev_type: identifies the device type
  * @dev_addr: the device's address on the bus.
  *
  * This macro initializes essential fields of a struct i2c_board_info,
  * declaring what has been provided on a particular board.  Optional
- * fields (such as the chip type, its associated irq, or device-specific
- * platform_data) are provided using conventional syntax.
+ * fields (such as associated irq, or device-specific platform_data)
+ * are provided using conventional syntax.
  */
-#define I2C_BOARD_INFO(driver,dev_addr) \
-       .driver_name = (driver), .addr = (dev_addr)
+#define I2C_BOARD_INFO(dev_type,dev_addr) \
+       .type = (dev_type), .addr = (dev_addr)
 
 
 /* Add-on boards should register/unregister their devices; e.g. a board
index f65e58a1d92557127032689e9224c545ced8178e..7d51cbca49ab230f15d5e8f1276d8ad5f5537b82 100644 (file)
@@ -18,8 +18,6 @@
 #ifndef _I2O_H
 #define _I2O_H
 
-#ifdef __KERNEL__              /* This file to be included by kernel only */
-
 #include <linux/i2o-dev.h>
 
 /* How many different OSM's are we allowing */
@@ -1255,5 +1253,4 @@ extern void i2o_dump_message(struct i2o_message *);
 extern void i2o_dump_hrt(struct i2o_controller *c);
 extern void i2o_debug_state(struct i2o_controller *c);
 
-#endif                         /* __KERNEL__ */
 #endif                         /* _I2O_H */
index 0edda411959cb3126d81a7f87c2542ff4f5a57be..9a2d762124de7684983cdb36a51dc3814b461a8f 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <linux/types.h>
 #include <linux/bitops.h>
+#include <linux/init.h>
 
 #if BITS_PER_LONG == 32
 # define IDR_BITS 5
@@ -115,4 +116,6 @@ void ida_remove(struct ida *ida, int id);
 void ida_destroy(struct ida *ida);
 void ida_init(struct ida *ida);
 
+void __init idr_init_cache(void);
+
 #endif /* __IDR_H__ */
index 0d9d7ea2c1cc55fc7a829d63c5bd0adaf6af1d27..5f200bac37496ea2d92a1b52fb8bf347b9f7f748 100644 (file)
@@ -1,9 +1,6 @@
 #ifndef _LINUX_IF_MACVLAN_H
 #define _LINUX_IF_MACVLAN_H
 
-#ifdef __KERNEL__
-
 extern struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *);
 
-#endif /* __KERNEL__ */
 #endif /* _LINUX_IF_MACVLAN_H */
index 675a7dbe86f876d68cbd7d9573b74e305e7091d8..1354080cf8cfa611d85f4594c2e7a74b2867f4ef 100644 (file)
 #ifndef _LINUX_INET_H
 #define _LINUX_INET_H
 
-#ifdef __KERNEL__
 #include <linux/types.h>
 
 extern __be32 in_aton(const char *str);
 extern int in4_pton(const char *src, int srclen, u8 *dst, int delim, const char **end);
 extern int in6_pton(const char *src, int srclen, u8 *dst, int delim, const char **end);
-#endif
 #endif /* _LINUX_INET_H */
index fb58c0493cf2f4524232ed95fd7b56371602ad28..21d658cdfa27769146ea52dae2cbf61b3de7f302 100644 (file)
@@ -147,6 +147,8 @@ extern unsigned int reset_devices;
 void setup_arch(char **);
 void prepare_namespace(void);
 
+extern void (*late_time_init)(void);
+
 #endif
   
 #ifndef MODULE
index b5fef13148bdd78692f6cf9aa523ca3662c1b7f4..f1fc7470d26ca540c27673074ac38447d28dcfbd 100644 (file)
@@ -289,6 +289,7 @@ struct softirq_action
 };
 
 asmlinkage void do_softirq(void);
+asmlinkage void __do_softirq(void);
 extern void open_softirq(int nr, void (*action)(struct softirq_action*), void *data);
 extern void softirq_init(void);
 #define __raise_softirq_irqoff(nr) do { or_softirq_pending(1UL << (nr)); } while (0)
index e4451d1da7534205dad7e7adfba595ab9d929064..ea6c18a8b0d442d13dabcdeca9961fb8540ca451 100644 (file)
@@ -4,6 +4,17 @@
 #include <linux/err.h>
 #include <linux/idr.h>
 #include <linux/rwsem.h>
+#include <linux/notifier.h>
+
+/*
+ * ipc namespace events
+ */
+#define IPCNS_MEMCHANGED   0x00000001   /* Notify lowmem size changed */
+#define IPCNS_CREATED  0x00000002   /* Notify new ipc namespace created */
+#define IPCNS_REMOVED  0x00000003   /* Notify ipc namespace removed */
+
+#define IPCNS_CALLBACK_PRI 0
+
 
 struct ipc_ids {
        int in_use;
@@ -30,15 +41,24 @@ struct ipc_namespace {
        size_t          shm_ctlall;
        int             shm_ctlmni;
        int             shm_tot;
+
+       struct notifier_block ipcns_nb;
 };
 
 extern struct ipc_namespace init_ipc_ns;
+extern atomic_t nr_ipc_ns;
 
 #ifdef CONFIG_SYSVIPC
 #define INIT_IPC_NS(ns)                .ns             = &init_ipc_ns,
-#else
+
+extern int register_ipcns_notifier(struct ipc_namespace *);
+extern int cond_register_ipcns_notifier(struct ipc_namespace *);
+extern int unregister_ipcns_notifier(struct ipc_namespace *);
+extern int ipcns_notify(unsigned long);
+
+#else /* CONFIG_SYSVIPC */
 #define INIT_IPC_NS(ns)
-#endif
+#endif /* CONFIG_SYSVIPC */
 
 #if defined(CONFIG_SYSVIPC) && defined(CONFIG_IPC_NS)
 extern void free_ipc_ns(struct kref *kref);
index c5bd28b69aec469087da75e93e28e7c789a4ca3f..7ebdb4fb4e54a3fe8943de5190f7f5de0ac59b08 100644 (file)
@@ -64,7 +64,7 @@
  * applications and another for userland applications.  The
  * capabilities are basically the same for both interface, although
  * the interfaces are somewhat different.  The stuff in the
- * #ifdef KERNEL below is the in-kernel interface.  The userland
+ * #ifdef __KERNEL__ below is the in-kernel interface.  The userland
  * interface is defined later in the file.  */
 
 
@@ -75,8 +75,7 @@
  * work for sockets.
  */
 #define IPMI_MAX_ADDR_SIZE 32
-struct ipmi_addr
-{
+struct ipmi_addr {
         /* Try to take these from the "Channel Medium Type" table
            in section 6.5 of the IPMI 1.5 manual. */
        int   addr_type;
@@ -90,8 +89,7 @@ struct ipmi_addr
  * 0), or IPMC_BMC_CHANNEL if communicating directly with the BMC.
  */
 #define IPMI_SYSTEM_INTERFACE_ADDR_TYPE        0x0c
-struct ipmi_system_interface_addr
-{
+struct ipmi_system_interface_addr {
        int           addr_type;
        short         channel;
        unsigned char lun;
@@ -100,10 +98,9 @@ struct ipmi_system_interface_addr
 /* An IPMB Address. */
 #define IPMI_IPMB_ADDR_TYPE            0x01
 /* Used for broadcast get device id as described in section 17.9 of the
-   IPMI 1.5 manual. */ 
+   IPMI 1.5 manual. */
 #define IPMI_IPMB_BROADCAST_ADDR_TYPE  0x41
-struct ipmi_ipmb_addr
-{
+struct ipmi_ipmb_addr {
        int           addr_type;
        short         channel;
        unsigned char slave_addr;
@@ -128,8 +125,7 @@ struct ipmi_ipmb_addr
  * message is a little weird, but this is required.
  */
 #define IPMI_LAN_ADDR_TYPE             0x04
-struct ipmi_lan_addr
-{
+struct ipmi_lan_addr {
        int           addr_type;
        short         channel;
        unsigned char privilege;
@@ -162,16 +158,14 @@ struct ipmi_lan_addr
  * byte of data in the response (as the spec shows the messages laid
  * out).
  */
-struct ipmi_msg
-{
+struct ipmi_msg {
        unsigned char  netfn;
        unsigned char  cmd;
        unsigned short data_len;
        unsigned char  __user *data;
 };
 
-struct kernel_ipmi_msg
-{
+struct kernel_ipmi_msg {
        unsigned char  netfn;
        unsigned char  cmd;
        unsigned short data_len;
@@ -239,12 +233,11 @@ typedef struct ipmi_user *ipmi_user_t;
  * used after the message is delivered, so the upper layer may use the
  * link to build a linked list, if it likes.
  */
-struct ipmi_recv_msg
-{
+struct ipmi_recv_msg {
        struct list_head link;
 
        /* The type of message as defined in the "Receive Types"
-           defines above. */
+          defines above. */
        int              recv_type;
 
        ipmi_user_t      user;
@@ -271,9 +264,8 @@ struct ipmi_recv_msg
 /* Allocate and free the receive message. */
 void ipmi_free_recv_msg(struct ipmi_recv_msg *msg);
 
-struct ipmi_user_hndl
-{
-        /* Routine type to call when a message needs to be routed to
+struct ipmi_user_hndl {
+       /* Routine type to call when a message needs to be routed to
           the upper layer.  This will be called with some locks held,
           the only IPMI routines that can be called are ipmi_request
           and the alloc/free operations.  The handler_data is the
@@ -368,9 +360,8 @@ int ipmi_request_supply_msgs(ipmi_user_t          user,
  * Poll the IPMI interface for the user.  This causes the IPMI code to
  * do an immediate check for information from the driver and handle
  * anything that is immediately pending.  This will not block in any
- * way.  This is useful if you need to implement polling from the user
- * for things like modifying the watchdog timeout when a panic occurs
- * or disabling the watchdog timer on a reboot.
+ * way.  This is useful if you need to spin waiting for something to
+ * happen in the IPMI driver.
  */
 void ipmi_poll_interface(ipmi_user_t user);
 
@@ -421,12 +412,6 @@ int ipmi_unregister_for_cmd(ipmi_user_t   user,
 int ipmi_get_maintenance_mode(ipmi_user_t user);
 int ipmi_set_maintenance_mode(ipmi_user_t user, int mode);
 
-/*
- * Allow run-to-completion mode to be set for the interface of
- * a specific user.
- */
-void ipmi_user_set_run_to_completion(ipmi_user_t user, int val);
-
 /*
  * When the user is created, it will not receive IPMI events by
  * default.  The user must set this to TRUE to get incoming events.
@@ -440,8 +425,7 @@ int ipmi_set_gets_events(ipmi_user_t user, int val);
  * every existing interface when a new watcher is registered with
  * ipmi_smi_watcher_register().
  */
-struct ipmi_smi_watcher
-{
+struct ipmi_smi_watcher {
        struct list_head link;
 
        /* You must set the owner to the current module, if you are in
@@ -512,8 +496,7 @@ int ipmi_validate_addr(struct ipmi_addr *addr, int len);
 
 
 /* Messages sent to the interface are this format. */
-struct ipmi_req
-{
+struct ipmi_req {
        unsigned char __user *addr; /* Address to send the message to. */
        unsigned int  addr_len;
 
@@ -538,12 +521,11 @@ struct ipmi_req
 
 /* Messages sent to the interface with timing parameters are this
    format. */
-struct ipmi_req_settime
-{
+struct ipmi_req_settime {
        struct ipmi_req req;
 
        /* See ipmi_request_settime() above for details on these
-           values. */
+          values. */
        int          retries;
        unsigned int retry_time_ms;
 };
@@ -560,8 +542,7 @@ struct ipmi_req_settime
                                             struct ipmi_req_settime)
 
 /* Messages received from the interface are this format. */
-struct ipmi_recv
-{
+struct ipmi_recv {
        int     recv_type; /* Is this a command, response or an
                              asyncronous event. */
 
@@ -607,13 +588,12 @@ struct ipmi_recv
                                              struct ipmi_recv)
 
 /* Register to get commands from other entities on this interface. */
-struct ipmi_cmdspec
-{
+struct ipmi_cmdspec {
        unsigned char netfn;
        unsigned char cmd;
 };
 
-/* 
+/*
  * Register to receive a specific command.  error values:
  *   - EFAULT - an address supplied was invalid.
  *   - EBUSY - The netfn/cmd supplied was already in use.
@@ -636,8 +616,7 @@ struct ipmi_cmdspec
  * else.  The chans field is a bitmask, (1 << channel) for each channel.
  * It may be IPMI_CHAN_ALL for all channels.
  */
-struct ipmi_cmdspec_chans
-{
+struct ipmi_cmdspec_chans {
        unsigned int netfn;
        unsigned int cmd;
        unsigned int chans;
@@ -659,7 +638,7 @@ struct ipmi_cmdspec_chans
 #define IPMICTL_UNREGISTER_FOR_CMD_CHANS _IOR(IPMI_IOC_MAGIC, 29,      \
                                             struct ipmi_cmdspec_chans)
 
-/* 
+/*
  * Set whether this interface receives events.  Note that the first
  * user registered for events will get all pending events for the
  * interface.  error values:
@@ -675,15 +654,18 @@ struct ipmi_cmdspec_chans
  * things it takes to determine your address (if not the BMC) and set
  * it for everyone else.  You should probably leave the LUN alone.
  */
-struct ipmi_channel_lun_address_set
-{
+struct ipmi_channel_lun_address_set {
        unsigned short channel;
        unsigned char  value;
 };
-#define IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 24, struct ipmi_channel_lun_address_set)
-#define IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD _IOR(IPMI_IOC_MAGIC, 25, struct ipmi_channel_lun_address_set)
-#define IPMICTL_SET_MY_CHANNEL_LUN_CMD    _IOR(IPMI_IOC_MAGIC, 26, struct ipmi_channel_lun_address_set)
-#define IPMICTL_GET_MY_CHANNEL_LUN_CMD    _IOR(IPMI_IOC_MAGIC, 27, struct ipmi_channel_lun_address_set)
+#define IPMICTL_SET_MY_CHANNEL_ADDRESS_CMD \
+       _IOR(IPMI_IOC_MAGIC, 24, struct ipmi_channel_lun_address_set)
+#define IPMICTL_GET_MY_CHANNEL_ADDRESS_CMD \
+       _IOR(IPMI_IOC_MAGIC, 25, struct ipmi_channel_lun_address_set)
+#define IPMICTL_SET_MY_CHANNEL_LUN_CMD \
+       _IOR(IPMI_IOC_MAGIC, 26, struct ipmi_channel_lun_address_set)
+#define IPMICTL_GET_MY_CHANNEL_LUN_CMD \
+       _IOR(IPMI_IOC_MAGIC, 27, struct ipmi_channel_lun_address_set)
 /* Legacy interfaces, these only set IPMB 0. */
 #define IPMICTL_SET_MY_ADDRESS_CMD     _IOR(IPMI_IOC_MAGIC, 17, unsigned int)
 #define IPMICTL_GET_MY_ADDRESS_CMD     _IOR(IPMI_IOC_MAGIC, 18, unsigned int)
@@ -694,8 +676,7 @@ struct ipmi_channel_lun_address_set
  * Get/set the default timing values for an interface.  You shouldn't
  * generally mess with these.
  */
-struct ipmi_timing_parms
-{
+struct ipmi_timing_parms {
        int          retries;
        unsigned int retry_time_ms;
 };
index 6e8cec50338000c31748bd1a8e5d4b28e26820cf..62b73668b60247c06da84bc8cca6919a9a34f6d6 100644 (file)
@@ -60,8 +60,7 @@ typedef struct ipmi_smi *ipmi_smi_t;
  * asynchronous data and messages and request them from the
  * interface.
  */
-struct ipmi_smi_msg
-{
+struct ipmi_smi_msg {
        struct list_head link;
 
        long    msgid;
@@ -74,12 +73,11 @@ struct ipmi_smi_msg
        unsigned char rsp[IPMI_MAX_MSG_LENGTH];
 
        /* Will be called when the system is done with the message
-           (presumably to free it). */
+          (presumably to free it). */
        void (*done)(struct ipmi_smi_msg *msg);
 };
 
-struct ipmi_smi_handlers
-{
+struct ipmi_smi_handlers {
        struct module *owner;
 
        /* The low-level interface cannot start sending messages to
@@ -231,7 +229,7 @@ static inline void ipmi_free_smi_msg(struct ipmi_smi_msg *msg)
    directory for this interface.  Note that the entry will
    automatically be dstroyed when the interface is destroyed. */
 int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
-                           read_proc_t *read_proc, write_proc_t *write_proc,
+                           read_proc_t *read_proc,
                            void *data, struct module *owner);
 
 #endif /* __LINUX_IPMI_SMI_H */
index 8f4c71759d73fd5ee45b664135650e61572f69c9..bbd42197298f14b95f78ffcc24d6d2db508de56f 100644 (file)
@@ -1,11 +1,6 @@
 #ifndef _LINUX_ISICOM_H
 #define _LINUX_ISICOM_H
 
-/*#define              ISICOM_DEBUG*/
-/*#define              ISICOM_DEBUG_DTR_RTS*/
-
-#ifdef __KERNEL__
-
 #define                YES     1
 #define                NO      0
 
@@ -85,6 +80,4 @@
 
 #define                ISI_TXOK                0x0001
 
-#endif /*      __KERNEL__      */
-
 #endif /*      ISICOM_H        */
diff --git a/include/linux/kbuild.h b/include/linux/kbuild.h
new file mode 100644 (file)
index 0000000..22a7219
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef __LINUX_KBUILD_H
+#define __LINUX_KBUILD_H
+
+#define DEFINE(sym, val) \
+        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define BLANK() asm volatile("\n->" : : )
+
+#define OFFSET(sym, str, mem) \
+       DEFINE(sym, offsetof(struct str, mem))
+
+#define COMMENT(x) \
+       asm volatile("\n->#" x)
+
+#endif
index cd6d02cf854d8e22d566c169326644ed5f708865..4d46e299afb5cb44003e42d894912d23fbe17a13 100644 (file)
@@ -20,6 +20,9 @@
 extern const char linux_banner[];
 extern const char linux_proc_banner[];
 
+#define USHORT_MAX     ((u16)(~0U))
+#define SHORT_MAX      ((s16)(USHORT_MAX>>1))
+#define SHORT_MIN      (-SHORT_MAX - 1)
 #define INT_MAX                ((int)(~0U>>1))
 #define INT_MIN                (-INT_MAX - 1)
 #define UINT_MAX       (~0U)
@@ -188,6 +191,7 @@ extern int log_buf_copy(char *dest, int idx, int len);
 extern int printk_ratelimit_jiffies;
 extern int printk_ratelimit_burst;
 extern int printk_ratelimit(void);
+extern int __ratelimit(int ratelimit_jiffies, int ratelimit_burst);
 extern int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst);
 extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
                                   unsigned int interval_msec);
@@ -255,6 +259,7 @@ extern enum system_states {
 #define TAINT_USER                     (1<<6)
 #define TAINT_DIE                      (1<<7)
 #define TAINT_OVERRIDDEN_ACPI_TABLE    (1<<8)
+#define TAINT_WARN                     (1<<9)
 
 extern void dump_stack(void) __cold;
 
@@ -333,33 +338,90 @@ extern void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
 #endif /* __LITTLE_ENDIAN */
 
 /*
- * min()/max() macros that also do
+ * min()/max()/clamp() macros that also do
  * strict type-checking.. See the
  * "unnecessary" pointer comparison.
  */
-#define min(x,y) ({ \
-       typeof(x) _x = (x);     \
-       typeof(y) _y = (y);     \
-       (void) (&_x == &_y);            \
-       _x < _y ? _x : _y; })
-
-#define max(x,y) ({ \
-       typeof(x) _x = (x);     \
-       typeof(y) _y = (y);     \
-       (void) (&_x == &_y);            \
-       _x > _y ? _x : _y; })
+#define min(x, y) ({                           \
+       typeof(x) _min1 = (x);                  \
+       typeof(y) _min2 = (y);                  \
+       (void) (&_min1 == &_min2);              \
+       _min1 < _min2 ? _min1 : _min2; })
+
+#define max(x, y) ({                           \
+       typeof(x) _max1 = (x);                  \
+       typeof(y) _max2 = (y);                  \
+       (void) (&_max1 == &_max2);              \
+       _max1 > _max2 ? _max1 : _max2; })
+
+/**
+ * clamp - return a value clamped to a given range with strict typechecking
+ * @val: current value
+ * @min: minimum allowable value
+ * @max: maximum allowable value
+ *
+ * This macro does strict typechecking of min/max to make sure they are of the
+ * same type as val.  See the unnecessary pointer comparisons.
+ */
+#define clamp(val, min, max) ({                        \
+       typeof(val) __val = (val);              \
+       typeof(min) __min = (min);              \
+       typeof(max) __max = (max);              \
+       (void) (&__val == &__min);              \
+       (void) (&__val == &__max);              \
+       __val = __val < __min ? __min: __val;   \
+       __val > __max ? __max: __val; })
 
 /*
  * ..and if you can't take the strict
  * types, you can specify one yourself.
  *
- * Or not use min/max at all, of course.
+ * Or not use min/max/clamp at all, of course.
+ */
+#define min_t(type, x, y) ({                   \
+       type __min1 = (x);                      \
+       type __min2 = (y);                      \
+       __min1 < __min2 ? __min1: __min2; })
+
+#define max_t(type, x, y) ({                   \
+       type __max1 = (x);                      \
+       type __max2 = (y);                      \
+       __max1 > __max2 ? __max1: __max2; })
+
+/**
+ * clamp_t - return a value clamped to a given range using a given type
+ * @type: the type of variable to use
+ * @val: current value
+ * @min: minimum allowable value
+ * @max: maximum allowable value
+ *
+ * This macro does no typechecking and uses temporary variables of type
+ * 'type' to make all the comparisons.
  */
-#define min_t(type,x,y) \
-       ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
-#define max_t(type,x,y) \
-       ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
+#define clamp_t(type, val, min, max) ({                \
+       type __val = (val);                     \
+       type __min = (min);                     \
+       type __max = (max);                     \
+       __val = __val < __min ? __min: __val;   \
+       __val > __max ? __max: __val; })
 
+/**
+ * clamp_val - return a value clamped to a given range using val's type
+ * @val: current value
+ * @min: minimum allowable value
+ * @max: maximum allowable value
+ *
+ * This macro does no typechecking and uses temporary variables of whatever
+ * type the input argument 'val' is.  This is useful when val is an unsigned
+ * type and min and max are literals that will otherwise be assigned a signed
+ * integer type.
+ */
+#define clamp_val(val, min, max) ({            \
+       typeof(val) __val = (val);              \
+       typeof(val) __min = (min);              \
+       typeof(val) __max = (max);              \
+       __val = __val < __min ? __min: __val;   \
+       __val > __max ? __max: __val; })
 
 /**
  * container_of - cast a member of a structure out to the containing structure
index a70b8a8f20058c60a5bc6916deeaceda5040ea6e..c45c962d1cc527e82aa37f8c76385d87fc236c4a 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/list.h>
 #include <linux/rbtree.h>
 #include <linux/rcupdate.h>
+#include <linux/sysctl.h>
 #include <asm/atomic.h>
 
 #ifdef __KERNEL__
@@ -67,6 +68,8 @@ struct key;
 #define KEY_OTH_SETATTR        0x00000020
 #define KEY_OTH_ALL    0x0000003f
 
+#define KEY_PERM_UNDEF 0xffffffff
+
 struct seq_file;
 struct user_struct;
 struct signal_struct;
@@ -208,16 +211,19 @@ extern struct key *request_key(struct key_type *type,
 
 extern struct key *request_key_with_auxdata(struct key_type *type,
                                            const char *description,
-                                           const char *callout_info,
+                                           const void *callout_info,
+                                           size_t callout_len,
                                            void *aux);
 
 extern struct key *request_key_async(struct key_type *type,
                                     const char *description,
-                                    const char *callout_info);
+                                    const void *callout_info,
+                                    size_t callout_len);
 
 extern struct key *request_key_async_with_auxdata(struct key_type *type,
                                                  const char *description,
-                                                 const char *callout_info,
+                                                 const void *callout_info,
+                                                 size_t callout_len,
                                                  void *aux);
 
 extern int wait_for_key_construction(struct key *key, bool intr);
@@ -229,6 +235,7 @@ extern key_ref_t key_create_or_update(key_ref_t keyring,
                                      const char *description,
                                      const void *payload,
                                      size_t plen,
+                                     key_perm_t perm,
                                      unsigned long flags);
 
 extern int key_update(key_ref_t key,
@@ -257,14 +264,18 @@ extern int keyring_add_key(struct key *keyring,
 
 extern struct key *key_lookup(key_serial_t id);
 
-#define key_serial(key) ((key) ? (key)->serial : 0)
+static inline key_serial_t key_serial(struct key *key)
+{
+       return key ? key->serial : 0;
+}
+
+#ifdef CONFIG_SYSCTL
+extern ctl_table key_sysctls[];
+#endif
 
 /*
  * the userspace interface
  */
-extern struct key root_user_keyring, root_session_keyring;
-extern int alloc_uid_keyring(struct user_struct *user,
-                            struct task_struct *ctx);
 extern void switch_uid_keyring(struct user_struct *new_user);
 extern int copy_keys(unsigned long clone_flags, struct task_struct *tsk);
 extern int copy_thread_group_keys(struct task_struct *tsk);
@@ -293,7 +304,6 @@ extern void key_init(void);
 #define make_key_ref(k, p)                     ({ NULL; })
 #define key_ref_to_ptr(k)              ({ NULL; })
 #define is_key_possessed(k)            0
-#define alloc_uid_keyring(u,c)         0
 #define switch_uid_keyring(u)          do { } while(0)
 #define __install_session_keyring(t, k)        ({ NULL; })
 #define copy_keys(f,t)                 0
@@ -306,10 +316,6 @@ extern void key_init(void);
 #define key_fsgid_changed(t)           do { } while(0)
 #define key_init()                     do { } while(0)
 
-/* Initial keyrings */
-extern struct key root_user_keyring;
-extern struct key root_session_keyring;
-
 #endif /* CONFIG_KEYS */
 #endif /* __KERNEL__ */
 #endif /* _LINUX_KEY_H */
index 3365945640c9a93d907efedb5c3ca707737797d2..656ee6b77a4a337d2dcdd728e8a1d79af83ba5ad 100644 (file)
@@ -49,5 +49,6 @@
 #define KEYCTL_SET_REQKEY_KEYRING      14      /* set default request-key keyring */
 #define KEYCTL_SET_TIMEOUT             15      /* set key timeout */
 #define KEYCTL_ASSUME_AUTHORITY                16      /* assume request_key() authorisation */
+#define KEYCTL_GET_SECURITY            17      /* get key security label */
 
 #endif /*  _LINUX_KEYCTL_H */
index 404f4464cb1aaf255b58c818a865ae4de2e103c7..29f62e1733ff4e23c61e4f25c75d6e5498e4ab93 100644 (file)
@@ -21,8 +21,6 @@
 #ifndef _LINUX_KFIFO_H
 #define _LINUX_KFIFO_H
 
-#ifdef __KERNEL__
-
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
 
@@ -151,7 +149,4 @@ static inline unsigned int kfifo_len(struct kfifo *fifo)
        return ret;
 }
 
-#else
-#warning "don't include kernel headers in userspace"
-#endif /* __KERNEL__ */
 #endif
index bafe178a381f19c98c7736370e5b31c5e8792ed2..73717ed9ea7912788cbe2c7f550eefd843d4aa97 100644 (file)
@@ -1,5 +1,3 @@
-#ifdef __KERNEL__
-
 #include <linux/mutex.h>
 
 typedef struct kobject *kobj_probe_t(dev_t, int *, void *);
@@ -10,5 +8,3 @@ int kobj_map(struct kobj_map *, dev_t, unsigned long, struct module *,
 void kobj_unmap(struct kobj_map *, dev_t, unsigned long);
 struct kobject *kobj_lookup(struct kobj_map *, dev_t, int *);
 struct kobj_map *kobj_map_init(kobj_probe_t *, struct mutex *);
-
-#endif
index caa3f411f15d0c48958e40d5369b4e16b9456b15..39e709f88aa001b73d1f9e7c6a9d33edac619c1f 100644 (file)
@@ -16,8 +16,6 @@
 #ifndef _KOBJECT_H_
 #define _KOBJECT_H_
 
-#ifdef __KERNEL__
-
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/sysfs.h>
@@ -224,5 +222,4 @@ static inline int kobject_action_type(const char *buf, size_t count,
 { return -EINVAL; }
 #endif
 
-#endif /* __KERNEL__ */
 #endif /* _KOBJECT_H_ */
index 5d185635786e129a35c28f475fdbb879cf78558b..0cef6badd6fb7cc07c445986e88bfaeb5e8903ed 100644 (file)
@@ -15,8 +15,6 @@
 #ifndef _KREF_H_
 #define _KREF_H_
 
-#ifdef __KERNEL__
-
 #include <linux/types.h>
 #include <asm/atomic.h>
 
@@ -29,5 +27,4 @@ void kref_init(struct kref *kref);
 void kref_get(struct kref *kref);
 int kref_put(struct kref *kref, void (*release) (struct kref *kref));
 
-#endif /* __KERNEL__ */
 #endif /* _KREF_H_ */
index 395a523d8c30c157985a48789016efea659c1196..d1dfe872ee308f854a4b7dd2113e124c4813d1ab 100644 (file)
@@ -548,11 +548,6 @@ struct ata_device {
        u64                     n_sectors;      /* size of device, if ATA */
        unsigned int            class;          /* ATA_DEV_xxx */
 
-       union {
-               u16             id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
-               u32             gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */
-       };
-
        u8                      pio_mode;
        u8                      dma_mode;
        u8                      xfer_mode;
@@ -574,8 +569,13 @@ struct ata_device {
        u16                     sectors;        /* Number of sectors per track */
 
        /* error history */
-       struct ata_ering        ering;
        int                     spdn_cnt;
+       struct ata_ering        ering;
+
+       union {
+               u16             id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
+               u32             gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */
+       };
 };
 
 /* Offset into struct ata_device.  Fields above it are maintained
index b4a939b6b6252349183aadccff2b7c7b9a6008da..08cf4f6518892a4364ce1a84332b407eab2b122f 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef _LINUX_LIST_H
 #define _LINUX_LIST_H
 
-#ifdef __KERNEL__
-
 #include <linux/stddef.h>
 #include <linux/poison.h>
 #include <linux/prefetch.h>
@@ -328,7 +326,7 @@ static inline int list_is_singular(const struct list_head *head)
        return !list_empty(head) && (head->next == head->prev);
 }
 
-static inline void __list_splice(struct list_head *list,
+static inline void __list_splice(const struct list_head *list,
                                 struct list_head *head)
 {
        struct list_head *first = list->next;
@@ -347,7 +345,8 @@ static inline void __list_splice(struct list_head *list,
  * @list: the new list to add.
  * @head: the place to add it in the first list.
  */
-static inline void list_splice(struct list_head *list, struct list_head *head)
+static inline void list_splice(const struct list_head *list,
+                               struct list_head *head)
 {
        if (!list_empty(list))
                __list_splice(list, head);
@@ -982,7 +981,4 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
                ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
             pos = rcu_dereference(pos->next))
 
-#else
-#warning "don't include kernel headers in userspace"
-#endif /* __KERNEL__ */
 #endif
index f2bb770e530aa82de96092a916e332d2a593a0d6..7a3aea845902966f91399b08ec209a65997ee67d 100644 (file)
@@ -34,7 +34,6 @@
 extern int mca_find_adapter(int id, int start);
 extern int mca_find_unused_adapter(int id, int start);
 
-extern int mca_is_adapter_used(int slot);
 extern int mca_mark_as_used(int slot);
 extern void mca_mark_as_unused(int slot);
 
index 8b1c4295848b77b6808c1f451434e02e599fffb2..e6608776bc96138c4fac9eea0b2a4126997bc7b8 100644 (file)
@@ -27,9 +27,6 @@ struct mm_struct;
 
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR
 
-extern void mm_init_cgroup(struct mm_struct *mm, struct task_struct *p);
-extern void mm_free_cgroup(struct mm_struct *mm);
-
 #define page_reset_bad_cgroup(page)    ((page)->page_cgroup = 0)
 
 extern struct page_cgroup *page_get_page_cgroup(struct page *page);
@@ -48,8 +45,10 @@ extern unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
 extern void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask);
 int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem);
 
+extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p);
+
 #define mm_match_cgroup(mm, cgroup)    \
-       ((cgroup) == rcu_dereference((mm)->mem_cgroup))
+       ((cgroup) == mem_cgroup_from_task((mm)->owner))
 
 extern int mem_cgroup_prepare_migration(struct page *page);
 extern void mem_cgroup_end_migration(struct page *page);
@@ -73,15 +72,6 @@ extern long mem_cgroup_calc_reclaim_inactive(struct mem_cgroup *mem,
                                struct zone *zone, int priority);
 
 #else /* CONFIG_CGROUP_MEM_RES_CTLR */
-static inline void mm_init_cgroup(struct mm_struct *mm,
-                                       struct task_struct *p)
-{
-}
-
-static inline void mm_free_cgroup(struct mm_struct *mm)
-{
-}
-
 static inline void page_reset_bad_cgroup(struct page *page)
 {
 }
index f80e0e331cb7e0f923feed2c26bb2cc03bd28e22..2f5f8a5ef2a08a5e796294275ee095cae2319fd5 100644 (file)
@@ -53,6 +53,13 @@ struct memory_notify {
 struct notifier_block;
 struct mem_section;
 
+/*
+ * Priorities for the hotplug memory callback routines (stored in decreasing
+ * order in the callback chain)
+ */
+#define SLAB_CALLBACK_PRI       1
+#define IPC_CALLBACK_PRI        10
+
 #ifndef CONFIG_MEMORY_HOTPLUG_SPARSE
 static inline int memory_dev_init(void)
 {
index 9fa1a8002ce206f27d5bd45ea916063fa6d6c9ad..a744383d16e956b7fbc6cf4be6f2cb179ec2c0f3 100644 (file)
@@ -382,7 +382,8 @@ void mlx4_free_hwq_res(struct mlx4_dev *mdev, struct mlx4_hwq_resources *wqres,
                       int size);
 
 int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
-                 struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq);
+                 struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq,
+                 int collapsed);
 void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq);
 
 int mlx4_qp_alloc(struct mlx4_dev *dev, int sqpn, struct mlx4_qp *qp);
index 8b7f4a5d4f6a5ce2e980a00ae3bc28b7898790e2..c31a9cd2a30e03a2672b8fa299c4d6a24a3fa186 100644 (file)
@@ -1066,6 +1066,19 @@ extern void unlink_file_vma(struct vm_area_struct *);
 extern struct vm_area_struct *copy_vma(struct vm_area_struct **,
        unsigned long addr, unsigned long len, pgoff_t pgoff);
 extern void exit_mmap(struct mm_struct *);
+
+#ifdef CONFIG_PROC_FS
+/* From fs/proc/base.c. callers must _not_ hold the mm's exe_file_lock */
+extern void added_exe_file_vma(struct mm_struct *mm);
+extern void removed_exe_file_vma(struct mm_struct *mm);
+#else
+static inline void added_exe_file_vma(struct mm_struct *mm)
+{}
+
+static inline void removed_exe_file_vma(struct mm_struct *mm)
+{}
+#endif /* CONFIG_PROC_FS */
+
 extern int may_expand_vm(struct mm_struct *mm, unsigned long npages);
 extern int install_special_mapping(struct mm_struct *mm,
                                   unsigned long addr, unsigned long len,
@@ -1230,8 +1243,6 @@ int drop_caches_sysctl_handler(struct ctl_table *, int, struct file *,
                                        void __user *, size_t *, loff_t *);
 unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
                        unsigned long lru_pages);
-void drop_pagecache(void);
-void drop_slab(void);
 
 #ifndef CONFIG_MMU
 #define randomize_va_space 0
index e2bae8dde35a2851e2ead741fbfda39636a23794..eb7c16cc95596fae106848e0a66b3b04f6f6b68a 100644 (file)
@@ -225,8 +225,15 @@ struct mm_struct {
        /* aio bits */
        rwlock_t                ioctx_list_lock;        /* aio lock */
        struct kioctx           *ioctx_list;
-#ifdef CONFIG_CGROUP_MEM_RES_CTLR
-       struct mem_cgroup *mem_cgroup;
+#ifdef CONFIG_MM_OWNER
+       struct task_struct *owner;      /* The thread group leader that */
+                                       /* owns the mm_struct.          */
+#endif
+
+#ifdef CONFIG_PROC_FS
+       /* store ref to file /proc/<pid>/exe symlink points to */
+       struct file *exe_file;
+       unsigned long num_exe_file_vmas;
 #endif
 };
 
index aad98003176f895ab9c361765109f981fe25be20..c463cd8a15a4aa028830ed8590988fdbf56f745c 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _LINUX_MMZONE_H
 #define _LINUX_MMZONE_H
 
-#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 #ifndef __GENERATING_BOUNDS_H
 
@@ -97,6 +96,7 @@ enum zone_stat_item {
        NR_UNSTABLE_NFS,        /* NFS unstable pages */
        NR_BOUNCE,
        NR_VMSCAN_WRITE,
+       NR_WRITEBACK_TEMP,      /* Writeback using temporary buffers */
 #ifdef CONFIG_NUMA
        NUMA_HIT,               /* allocated in intended node */
        NUMA_MISS,              /* allocated in non intended node */
@@ -1004,5 +1004,4 @@ unsigned long __init node_memmap_size_bytes(int, unsigned long, unsigned long);
 
 #endif /* !__GENERATING_BOUNDS.H */
 #endif /* !__ASSEMBLY__ */
-#endif /* __KERNEL__ */
 #endif /* _LINUX_MMZONE_H */
index 139d49d2f078d5573f166475c99873916a041515..d73eceaa7afb481e25f623fbf9a7aec92117f808 100644 (file)
@@ -368,4 +368,15 @@ struct virtio_device_id {
 };
 #define VIRTIO_DEV_ANY_ID      0xffffffff
 
+/* i2c */
+
+#define I2C_NAME_SIZE  20
+#define I2C_MODULE_PREFIX "i2c:"
+
+struct i2c_device_id {
+       char name[I2C_NAME_SIZE];
+       kernel_ulong_t driver_data;     /* Data private to the driver */
+};
+
+
 #endif /* LINUX_MOD_DEVICETABLE_H */
index b4836d58f428993e6d7f468d742d6a99ed422e8a..4374d1adeb4b755b4227bccf1f3afaa0b214fc35 100644 (file)
@@ -10,7 +10,6 @@
  */
 #ifndef _LINUX_MOUNT_H
 #define _LINUX_MOUNT_H
-#ifdef __KERNEL__
 
 #include <linux/types.h>
 #include <linux/list.h>
@@ -114,5 +113,4 @@ extern void mark_mounts_for_expiry(struct list_head *mounts);
 extern spinlock_t vfsmount_lock;
 extern dev_t name_to_dev_t(char *name);
 
-#endif
 #endif /* _LINUX_MOUNT_H */
index 10a3d5a1abffb30fd9b158148b26379416cd1fe0..6f3b8e79a9912c0aa4a5d06e1d07742387fd1346 100644 (file)
@@ -49,16 +49,26 @@ struct msginfo {
        unsigned short  msgseg; 
 };
 
+/*
+ * Scaling factor to compute msgmni:
+ * the memory dedicated to msg queues (msgmni * msgmnb) should occupy
+ * at most 1/MSG_MEM_SCALE of the lowmem (see the formula in ipc/msg.c):
+ * up to 8MB       : msgmni = 16 (MSGMNI)
+ * 4 GB            : msgmni = 8K
+ * more than 16 GB : msgmni = 32K (IPCMNI)
+ */
+#define MSG_MEM_SCALE 32
+
 #define MSGMNI    16   /* <= IPCMNI */     /* max # of msg queue identifiers */
 #define MSGMAX  8192   /* <= INT_MAX */   /* max size of message (bytes) */
 #define MSGMNB 16384   /* <= INT_MAX */   /* default max size of a message queue */
 
 /* unused */
-#define MSGPOOL (MSGMNI*MSGMNB/1024)  /* size in kilobytes of message pool */
+#define MSGPOOL (MSGMNI * MSGMNB) /* size in bytes of message pool */
 #define MSGTQL  MSGMNB            /* number of system message headers */
 #define MSGMAP  MSGMNB            /* number of entries in message map */
 #define MSGSSZ  16                /* message segment size */
-#define __MSGSEG ((MSGPOOL*1024)/ MSGSSZ) /* max no. of segments */
+#define __MSGSEG (MSGPOOL / MSGSSZ) /* max no. of segments */
 #define MSGSEG (__MSGSEG <= 0xffff ? __MSGSEG : 0xffff)
 
 #ifdef __KERNEL__
index 94bb46d82efd74fedc12df205e43cc2f9fc8f167..8f293922720735ee164cf4b5183f064d09e9f5a6 100644 (file)
@@ -22,6 +22,7 @@ struct msi_desc {
                __u8    masked  : 1;
                __u8    is_64   : 1;    /* Address size: 0=32bit 1=64bit  */
                __u8    pos;            /* Location of the msi capability */
+               __u32   maskbits_mask;  /* mask bits mask */
                __u16   entry_nr;       /* specific enabled entry         */
                unsigned default_irq;   /* default pre-assigned irq       */
        }msi_attrib;
index 986572081e19053b84061d7ecfc20702fbce2b59..155719dab813e2fac8b52bc5a3ae3afdbcbbc8ce 100644 (file)
@@ -56,9 +56,11 @@ struct nbd_device {
        int magic;
 
        spinlock_t queue_lock;
-       struct list_head queue_head;/* Requests are added here...       */
+       struct list_head queue_head;    /* Requests waiting result */
        struct request *active_req;
        wait_queue_head_t active_wq;
+       struct list_head waiting_queue; /* Requests to be sent */
+       wait_queue_head_t waiting_wq;
 
        struct mutex tx_lock;
        struct gendisk *disk;
@@ -86,11 +88,7 @@ struct nbd_request {
        char handle[8];
        __be64 from;
        __be32 len;
-}
-#ifdef __GNUC__
-       __attribute__ ((packed))
-#endif
-;
+} __attribute__ ((packed));
 
 /*
  * This is the reply packet that nbd-server sends back to the client after
index bdb4c8ae6924e4a0acc0ad123cd43cf8848f2721..4b0bec477846730ed8263c3ad097b3572e839e7d 100644 (file)
@@ -8,8 +8,6 @@
 #ifndef _LINUX_NCP_FS_I
 #define _LINUX_NCP_FS_I
 
-#ifdef __KERNEL__
-
 /*
  * This is the ncpfs part of the inode structure. This must contain
  * all the information we need to work with an inode after creation.
@@ -28,6 +26,4 @@ struct ncp_inode_info {
        struct inode vfs_inode;
 };
 
-#endif /* __KERNEL__ */
-
 #endif /* _LINUX_NCP_FS_I */
index fb0713b6ffaf910d6d5d58462d29f5fe2db03f8f..bec1062a25a1e83146e8478f2bb8443a05fcf288 100644 (file)
@@ -166,6 +166,7 @@ struct netlink_skb_parms
        __u32                   dst_group;
        kernel_cap_t            eff_cap;
        __u32                   loginuid;       /* Login (audit) uid */
+       __u32                   sessionid;      /* Session id (audit) */
        __u32                   sid;            /* SELinux security id */
 };
 
index 20dfed590183cb0d0ad94998cfde168fdc7e97b3..0ff6224d172a90c4a9dd8122c6b9358e129f53cf 100644 (file)
@@ -121,6 +121,10 @@ extern int raw_notifier_chain_register(struct raw_notifier_head *nh,
 extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
                struct notifier_block *nb);
 
+extern int blocking_notifier_chain_cond_register(
+               struct blocking_notifier_head *nh,
+               struct notifier_block *nb);
+
 extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
                struct notifier_block *nb);
 extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
index 6dc11959770c23da51f4fa394c9b694f60aa1ff1..afe338217d91cc0b3e0166c0d9511970f4401871 100644 (file)
@@ -1,6 +1,5 @@
 #ifndef _LINUX_OF_DEVICE_H
 #define _LINUX_OF_DEVICE_H
-#ifdef __KERNEL__
 
 #include <linux/device.h>
 #include <linux/of.h>
@@ -25,5 +24,4 @@ static inline void of_device_free(struct of_device *dev)
        of_release_dev(&dev->dev);
 }
 
-#endif /* __KERNEL__ */
 #endif /* _LINUX_OF_DEVICE_H */
index 292491324b010f1184b48241bbc066f9377c8800..96acd0dae2419bd42fe102e60df664304c83cfba 100644 (file)
@@ -20,8 +20,6 @@
 /* Include the pci register defines */
 #include <linux/pci_regs.h>
 
-struct pci_vpd;
-
 /*
  * The PCI interface treats multi-function devices as independent
  * devices.  The slot/function address of each device is encoded
@@ -131,6 +129,8 @@ struct pci_cap_saved_state {
 };
 
 struct pcie_link_state;
+struct pci_vpd;
+
 /*
  * The pci_dev structure is used to describe PCI devices.
  */
@@ -254,7 +254,7 @@ static inline void pci_add_saved_cap(struct pci_dev *pci_dev,
 #define PCI_NUM_RESOURCES      11
 
 #ifndef PCI_BUS_NUM_RESOURCES
-#define PCI_BUS_NUM_RESOURCES  8
+#define PCI_BUS_NUM_RESOURCES  16
 #endif
 
 #define PCI_REGION_FLAG_MASK   0x0fU   /* These bits of resource flags tell us the PCI region flags */
@@ -666,6 +666,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 
 void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
                  void *userdata);
+int pci_cfg_space_size_ext(struct pci_dev *dev, unsigned check_exp_pcix);
 int pci_cfg_space_size(struct pci_dev *dev);
 unsigned char pci_bus_max_busnr(struct pci_bus *bus);
 
@@ -701,6 +702,8 @@ static inline int pci_enable_msi(struct pci_dev *dev)
        return -1;
 }
 
+static inline void pci_msi_shutdown(struct pci_dev *dev)
+{ }
 static inline void pci_disable_msi(struct pci_dev *dev)
 { }
 
@@ -710,6 +713,8 @@ static inline int pci_enable_msix(struct pci_dev *dev,
        return -1;
 }
 
+static inline void pci_msix_shutdown(struct pci_dev *dev)
+{ }
 static inline void pci_disable_msix(struct pci_dev *dev)
 { }
 
@@ -720,9 +725,11 @@ static inline void pci_restore_msi_state(struct pci_dev *dev)
 { }
 #else
 extern int pci_enable_msi(struct pci_dev *dev);
+extern void pci_msi_shutdown(struct pci_dev *dev);
 extern void pci_disable_msi(struct pci_dev *dev);
 extern int pci_enable_msix(struct pci_dev *dev,
        struct msix_entry *entries, int nvec);
+extern void pci_msix_shutdown(struct pci_dev *dev);
 extern void pci_disable_msix(struct pci_dev *dev);
 extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
 extern void pci_restore_msi_state(struct pci_dev *dev);
@@ -1053,5 +1060,13 @@ extern unsigned long pci_cardbus_mem_size;
 
 extern int pcibios_add_platform_entries(struct pci_dev *dev);
 
+#ifdef CONFIG_PCI_MMCONFIG
+extern void __init pci_mmcfg_early_init(void);
+extern void __init pci_mmcfg_late_init(void);
+#else
+static inline void pci_mmcfg_early_init(void) { }
+static inline void pci_mmcfg_late_init(void) { }
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */
index 70eb3c803d47825118844484c60384b523534f41..e5a53daf17f14c88705c2aa7a752e515a0b23dcd 100644 (file)
 #define PCI_DEVICE_ID_INTEL_82443GX_0  0x71a0
 #define PCI_DEVICE_ID_INTEL_82443GX_2  0x71a2
 #define PCI_DEVICE_ID_INTEL_82372FB_1  0x7601
+#define PCI_DEVICE_ID_INTEL_SCH_LPC    0x8119
+#define PCI_DEVICE_ID_INTEL_SCH_IDE    0x811a
 #define PCI_DEVICE_ID_INTEL_82454GX    0x84c4
 #define PCI_DEVICE_ID_INTEL_82450GX    0x84c5
 #define PCI_DEVICE_ID_INTEL_82451NX    0x84ca
index 1ac969724bb2fff929c397be1cbdcdf007a61953..d746a2abb322590a7e891762638e774ec0efe2b5 100644 (file)
@@ -4,7 +4,6 @@
 #include <linux/preempt.h>
 #include <linux/slab.h> /* For kmalloc() */
 #include <linux/smp.h>
-#include <linux/string.h> /* For memset() */
 #include <linux/cpumask.h>
 
 #include <asm/percpu.h>
index 012cd558189b443e6f3856426313cd783c6a36ce..a84e9ff9b27e9d59cfd1f2d0e8b3403e21b07ca0 100644 (file)
@@ -105,10 +105,6 @@ struct exec_domain {
  */
 #define personality(pers)      (pers & PER_MASK)
 
-/*
- * Personality of the currently running process.
- */
-#define get_personality                (current->personality)
 
 /*
  * Change personality of the currently running process.
index 96f4048a6cc37bd1a8970c30a1037c1f5f27ad04..02268c54c250767b8ec3eda32b4c68edfe768ff5 100644 (file)
@@ -27,14 +27,17 @@ struct phm_regs {
 
 #define PH_IOC_MAGIC           'p'
 #define PHN_GET_REG            _IOWR(PH_IOC_MAGIC, 0, struct phm_reg *)
-#define PHN_SET_REG            _IOW (PH_IOC_MAGIC, 1, struct phm_reg *)
+#define PHN_SET_REG            _IOW(PH_IOC_MAGIC, 1, struct phm_reg *)
 #define PHN_GET_REGS           _IOWR(PH_IOC_MAGIC, 2, struct phm_regs *)
-#define PHN_SET_REGS           _IOW (PH_IOC_MAGIC, 3, struct phm_regs *)
+#define PHN_SET_REGS           _IOW(PH_IOC_MAGIC, 3, struct phm_regs *)
 /* this ioctl tells the driver, that the caller is not OpenHaptics and might
  * use improved registers update (no more phantom switchoffs when using
  * libphantom) */
-#define PHN_NOT_OH             _IO  (PH_IOC_MAGIC, 4)
-#define PH_IOC_MAXNR           4
+#define PHN_NOT_OH             _IO(PH_IOC_MAGIC, 4)
+#define PHN_GETREG             _IOWR(PH_IOC_MAGIC, 5, struct phm_reg)
+#define PHN_SETREG             _IOW(PH_IOC_MAGIC, 6, struct phm_reg)
+#define PHN_GETREGS            _IOWR(PH_IOC_MAGIC, 7, struct phm_regs)
+#define PHN_SETREGS            _IOW(PH_IOC_MAGIC, 8, struct phm_regs)
 
 #define PHN_CONTROL            0x6     /* control byte in iaddr space */
 #define PHN_CTL_AMP            0x1     /*   switch after torques change */
index c7980810eb09d96becad505f2f9349e9a9a56685..c21c7e8124a7bb7bde92937fc37cf0810598d091 100644 (file)
@@ -60,7 +60,7 @@ struct pid
        /* lists of tasks that use this pid */
        struct hlist_head tasks[PIDTYPE_MAX];
        struct rcu_head rcu;
-       int level;
+       unsigned int level;
        struct upid numbers[1];
 };
 
@@ -89,9 +89,11 @@ extern struct pid *get_task_pid(struct task_struct *task, enum pid_type type);
  * attach_pid() and detach_pid() must be called with the tasklist_lock
  * write-held.
  */
-extern int attach_pid(struct task_struct *task, enum pid_type type,
-                     struct pid *pid);
+extern void attach_pid(struct task_struct *task, enum pid_type type,
+                       struct pid *pid);
 extern void detach_pid(struct task_struct *task, enum pid_type);
+extern void change_pid(struct task_struct *task, enum pid_type,
+                       struct pid *pid);
 extern void transfer_pid(struct task_struct *old, struct task_struct *new,
                         enum pid_type);
 
index fcd61fa2c833e415ab823e03532bd4880b16be79..caff5283d15c6e11fe838ffad6b2877077af490e 100644 (file)
@@ -20,7 +20,7 @@ struct pid_namespace {
        int last_pid;
        struct task_struct *child_reaper;
        struct kmem_cache *pid_cachep;
-       int level;
+       unsigned int level;
        struct pid_namespace *parent;
 #ifdef CONFIG_PROC_FS
        struct vfsmount *proc_mnt;
index 1de72cbbe0d1af6a4ea9891adb659aaddfcd478d..39a7ee859b671cfc57f5fcd9e063fc3031e96f84 100644 (file)
@@ -21,8 +21,6 @@
 #ifndef _LINUX_PM_H
 #define _LINUX_PM_H
 
-#ifdef __KERNEL__
-
 #include <linux/list.h>
 #include <asm/atomic.h>
 #include <asm/errno.h>
@@ -225,6 +223,4 @@ extern unsigned int pm_flags;
 #define PM_APM 1
 #define PM_ACPI        2
 
-#endif /* __KERNEL__ */
-
 #endif /* _LINUX_PM_H */
index b2f05c230f4b8db61984950489173980c003178a..2f3bcf73052cc0de06a42db578920e1a3f8207f6 100644 (file)
@@ -6,8 +6,6 @@
 #ifndef _LINUX_PNP_H
 #define _LINUX_PNP_H
 
-#ifdef __KERNEL__
-
 #include <linux/device.h>
 #include <linux/list.h>
 #include <linux/errno.h>
@@ -466,6 +464,4 @@ static inline void pnp_unregister_driver(struct pnp_driver *drv) { }
 #define pnp_dbg(format, arg...) do {} while (0)
 #endif
 
-#endif /* __KERNEL__ */
-
 #endif /* _LINUX_PNP_H */
index a9c31be7052c4bcbd4593963ebf32303b338e04f..9f31683728fd7e2c59f738ae35ab6835066270c1 100644 (file)
 #define LIST_POISON1  ((void *) 0x00100100)
 #define LIST_POISON2  ((void *) 0x00200200)
 
+/********** include/linux/timer.h **********/
+/*
+ * Magic number "tsta" to indicate a static timer initializer
+ * for the object debugging code.
+ */
+#define TIMER_ENTRY_STATIC     ((void *) 0x74737461)
+
 /********** mm/slab.c **********/
 /*
  * Magic nums for obj red zoning.
index 9b6c935f69cf6d1986677b968bb17c2ca000e4b0..9883bc9422621c86b9417a111f8ad1b9d14403dd 100644 (file)
@@ -9,7 +9,6 @@
 
 struct net;
 struct completion;
-
 /*
  * The proc filesystem constants/structures
  */
@@ -41,7 +40,7 @@ enum {
  * /proc file has a parent, but "subdir" is NULL for all
  * non-directory entries).
  *
- * "get_info" is called at "read", while "owner" is used to protect module
+ * "owner" is used to protect module
  * from unloading while proc_dir_entry is in use
  */
 
@@ -49,7 +48,6 @@ typedef       int (read_proc_t)(char *page, char **start, off_t off,
                          int count, int *eof, void *data);
 typedef        int (write_proc_t)(struct file *file, const char __user *buffer,
                           unsigned long count, void *data);
-typedef int (get_info_t)(char *, char **, off_t, int);
 
 struct proc_dir_entry {
        unsigned int low_ino;
@@ -70,7 +68,6 @@ struct proc_dir_entry {
         * somewhere.
         */
        const struct file_operations *proc_fops;
-       get_info_t *get_info;
        struct module *owner;
        struct proc_dir_entry *next, *parent, *subdir;
        void *data;
@@ -97,10 +94,6 @@ struct vmcore {
 
 #ifdef CONFIG_PROC_FS
 
-extern struct proc_dir_entry proc_root;
-extern struct proc_dir_entry *proc_root_fs;
-extern struct proc_dir_entry *proc_bus;
-extern struct proc_dir_entry *proc_root_driver;
 extern struct proc_dir_entry *proc_root_kcore;
 
 extern spinlock_t proc_subdir_lock;
@@ -123,9 +116,10 @@ void de_put(struct proc_dir_entry *de);
 
 extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
                                                struct proc_dir_entry *parent);
-struct proc_dir_entry *proc_create(const char *name, mode_t mode,
+struct proc_dir_entry *proc_create_data(const char *name, mode_t mode,
                                struct proc_dir_entry *parent,
-                               const struct file_operations *proc_fops);
+                               const struct file_operations *proc_fops,
+                               void *data);
 extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
 
 extern struct vfsmount *proc_mnt;
@@ -180,6 +174,12 @@ extern struct proc_dir_entry *proc_mkdir(const char *,struct proc_dir_entry *);
 extern struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode,
                        struct proc_dir_entry *parent);
 
+static inline struct proc_dir_entry *proc_create(const char *name, mode_t mode,
+       struct proc_dir_entry *parent, const struct file_operations *proc_fops)
+{
+       return proc_create_data(name, mode, parent, proc_fops, NULL);
+}
+
 static inline struct proc_dir_entry *create_proc_read_entry(const char *name,
        mode_t mode, struct proc_dir_entry *base, 
        read_proc_t *read_proc, void * data)
@@ -192,24 +192,19 @@ static inline struct proc_dir_entry *create_proc_read_entry(const char *name,
        return res;
 }
  
-static inline struct proc_dir_entry *create_proc_info_entry(const char *name,
-       mode_t mode, struct proc_dir_entry *base, get_info_t *get_info)
-{
-       struct proc_dir_entry *res=create_proc_entry(name,mode,base);
-       if (res) res->get_info=get_info;
-       return res;
-}
-
 extern struct proc_dir_entry *proc_net_fops_create(struct net *net,
        const char *name, mode_t mode, const struct file_operations *fops);
 extern void proc_net_remove(struct net *net, const char *name);
 extern struct proc_dir_entry *proc_net_mkdir(struct net *net, const char *name,
        struct proc_dir_entry *parent);
 
-#else
+/* While the {get|set|dup}_mm_exe_file functions are for mm_structs, they are
+ * only needed to implement /proc/<pid>|self/exe so we define them here. */
+extern void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file);
+extern struct file *get_mm_exe_file(struct mm_struct *mm);
+extern void dup_mm_exe_file(struct mm_struct *oldmm, struct mm_struct *newmm);
 
-#define proc_root_driver NULL
-#define proc_bus NULL
+#else
 
 #define proc_net_fops_create(net, name, mode, fops)  ({ (void)(mode), NULL; })
 static inline void proc_net_remove(struct net *net, const char *name) {}
@@ -226,6 +221,12 @@ static inline struct proc_dir_entry *proc_create(const char *name,
 {
        return NULL;
 }
+static inline struct proc_dir_entry *proc_create_data(const char *name,
+       mode_t mode, struct proc_dir_entry *parent,
+       const struct file_operations *proc_fops, void *data)
+{
+       return NULL;
+}
 #define remove_proc_entry(name, parent) do {} while (0)
 
 static inline struct proc_dir_entry *proc_symlink(const char *name,
@@ -236,16 +237,11 @@ static inline struct proc_dir_entry *proc_mkdir(const char *name,
 static inline struct proc_dir_entry *create_proc_read_entry(const char *name,
        mode_t mode, struct proc_dir_entry *base, 
        read_proc_t *read_proc, void * data) { return NULL; }
-static inline struct proc_dir_entry *create_proc_info_entry(const char *name,
-       mode_t mode, struct proc_dir_entry *base, get_info_t *get_info)
-       { return NULL; }
 
 struct tty_driver;
 static inline void proc_tty_register_driver(struct tty_driver *driver) {};
 static inline void proc_tty_unregister_driver(struct tty_driver *driver) {};
 
-extern struct proc_dir_entry proc_root;
-
 static inline int pid_ns_prepare_proc(struct pid_namespace *ns)
 {
        return 0;
@@ -255,6 +251,19 @@ static inline void pid_ns_release_proc(struct pid_namespace *ns)
 {
 }
 
+static inline void set_mm_exe_file(struct mm_struct *mm,
+                                  struct file *new_exe_file)
+{}
+
+static inline struct file *get_mm_exe_file(struct mm_struct *mm)
+{
+       return NULL;
+}
+
+static inline void dup_mm_exe_file(struct mm_struct *oldmm,
+                                  struct mm_struct *newmm)
+{}
+
 #endif /* CONFIG_PROC_FS */
 
 #if !defined(CONFIG_PROC_KCORE)
index ff576d1db67de07a090f40bcd93d75c71d879500..05c1cc736937fcc48d5df8781a6ad1b391f73807 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef _LINUX_PROFILE_H
 #define _LINUX_PROFILE_H
 
-#ifdef __KERNEL__
-
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/cpumask.h>
@@ -118,6 +116,4 @@ static inline void unregister_timer_hook(int (*hook)(struct pt_regs *))
 
 #endif /* CONFIG_PROFILING */
 
-#endif /* __KERNEL__ */
-
 #endif /* _LINUX_PROFILE_H */
index 2c3b3cad92bec050b18605cffe39784f774f09d0..5afc1b23346d1f04536ea9339c1790b1cceeef3a 100644 (file)
@@ -77,6 +77,19 @@ void prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl)
        local_irq_restore(flags);
 }
 
+/*
+ * Limit the time part in order to ensure there are some bits left for the
+ * cycle counter and fraction multiply.
+ */
+#define PROP_MAX_SHIFT (3*BITS_PER_LONG/4)
+
+#define PROP_FRAC_SHIFT                (BITS_PER_LONG - PROP_MAX_SHIFT - 1)
+#define PROP_FRAC_BASE         (1UL << PROP_FRAC_SHIFT)
+
+void __prop_inc_percpu_max(struct prop_descriptor *pd,
+                          struct prop_local_percpu *pl, long frac);
+
+
 /*
  * ----- SINGLE ------
  */
index ebe0c17039cf0f8dec6d6207da29052463a610d3..f98501ba557eea676a827aed770d57b0b4b12c56 100644 (file)
@@ -98,6 +98,10 @@ extern void ptrace_untrace(struct task_struct *child);
 extern int ptrace_may_attach(struct task_struct *task);
 extern int __ptrace_may_attach(struct task_struct *task);
 
+static inline int ptrace_reparented(struct task_struct *child)
+{
+       return child->real_parent != child->parent;
+}
 static inline void ptrace_link(struct task_struct *child,
                               struct task_struct *new_parent)
 {
index 8ab630b67fcca8c3d0d58237915f2a8b3f0d936a..81a1a02d4566103b9dffc54771b4bde0d61f3358 100644 (file)
@@ -94,6 +94,7 @@ extern int sync_page_io(struct block_device *bdev, sector_t sector, int size,
 extern void md_do_sync(mddev_t *mddev);
 extern void md_new_event(mddev_t *mddev);
 extern void md_allow_write(mddev_t *mddev);
+extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
 
 #endif /* CONFIG_MD */
 #endif 
index 7bb6d1abf71e85944bc20e82243cc88df8353e71..812ffa590cff097ce5303266088fa1ec7ffe55a0 100644 (file)
@@ -84,6 +84,10 @@ struct mdk_rdev_s
 #define        AllReserved     6               /* If whole device is reserved for
                                         * one array */
 #define        AutoDetected    7               /* added by auto-detect */
+#define Blocked                8               /* An error occured on an externally
+                                        * managed array, don't allow writes
+                                        * until it is cleared */
+       wait_queue_head_t blocked_wait;
 
        int desc_nr;                    /* descriptor index in the superblock */
        int raid_disk;                  /* role of device in array */
index b3dccd68629e1c0481dd41471798ec25884fafd8..b3aa05baab8ac439a569936e0d5bf60135f81fab 100644 (file)
@@ -33,8 +33,6 @@
 #ifndef __LINUX_RCUCLASSIC_H
 #define __LINUX_RCUCLASSIC_H
 
-#ifdef __KERNEL__
-
 #include <linux/cache.h>
 #include <linux/spinlock.h>
 #include <linux/threads.h>
@@ -163,5 +161,4 @@ extern long rcu_batches_completed_bh(void);
 #define rcu_enter_nohz()       do { } while (0)
 #define rcu_exit_nohz()                do { } while (0)
 
-#endif /* __KERNEL__ */
 #endif /* __LINUX_RCUCLASSIC_H */
index 37a642c54871f24166bec8e9b23b73e3369848bb..8082d6587a0f6544a1ec6c28af922dc01a4b90ea 100644 (file)
@@ -33,8 +33,6 @@
 #ifndef __LINUX_RCUPDATE_H
 #define __LINUX_RCUPDATE_H
 
-#ifdef __KERNEL__
-
 #include <linux/cache.h>
 #include <linux/spinlock.h>
 #include <linux/threads.h>
@@ -245,5 +243,4 @@ extern long rcu_batches_completed_bh(void);
 extern void rcu_init(void);
 extern int rcu_needs_cpu(int cpu);
 
-#endif /* __KERNEL__ */
 #endif /* __LINUX_RCUPDATE_H */
index d038aa6e5ee1b4dd64cba0e8e193439c16f010f7..8a05c7e20bc4e780c7765d34a2f9abda11436658 100644 (file)
@@ -33,8 +33,6 @@
 #ifndef __LINUX_RCUPREEMPT_H
 #define __LINUX_RCUPREEMPT_H
 
-#ifdef __KERNEL__
-
 #include <linux/cache.h>
 #include <linux/spinlock.h>
 #include <linux/threads.h>
@@ -104,5 +102,4 @@ static inline void rcu_exit_nohz(void)
 #define rcu_exit_nohz()                do { } while (0)
 #endif /* CONFIG_NO_HZ */
 
-#endif /* __KERNEL__ */
 #endif /* __LINUX_RCUPREEMPT_H */
index 21cd6b2a5c42415628be9780cb4894168abe1c87..b99ae073192a85113969ab0dededd08f5a0ea1cc 100644 (file)
@@ -32,7 +32,6 @@
 #ifndef __LINUX_RCUPREEMPT_TRACE_H
 #define __LINUX_RCUPREEMPT_TRACE_H
 
-#ifdef __KERNEL__
 #include <linux/types.h>
 #include <linux/kernel.h>
 
@@ -95,5 +94,4 @@ extern void rcupreempt_trace_done_remove(struct rcupreempt_trace *trace);
 extern void rcupreempt_trace_invoke(struct rcupreempt_trace *trace);
 extern void rcupreempt_trace_next_add(struct rcupreempt_trace *trace);
 
-#endif /* __KERNEL__ */
 #endif /* __LINUX_RCUPREEMPT_TRACE_H */
index db5ef9b83c3ff366be21465ffe2a86a5602032f4..336ee43ed7d8897eb9a1b4c7453123bf7ab3ebc8 100644 (file)
@@ -177,7 +177,6 @@ struct reiserfs_journal {
        struct reiserfs_journal_cnode *j_last;  /* newest journal block */
        struct reiserfs_journal_cnode *j_first; /*  oldest journal block.  start here for traverse */
 
-       struct file *j_dev_file;
        struct block_device *j_dev_bd;
        int j_1st_reserved_block;       /* first block on s_dev of reserved area journal */
 
index 61363ce896d5988857ed440087147eb27bc4e1c5..6d9e1fca098c468b49287791e181f6e4f51e7d54 100644 (file)
@@ -9,6 +9,8 @@
  *
  * Author: Pavel Emelianov <xemul@openvz.org>
  *
+ * See Documentation/controllers/resource_counter.txt for more
+ * info about what this counter is.
  */
 
 #include <linux/cgroup.h>
@@ -24,6 +26,10 @@ struct res_counter {
         * the current resource consumption level
         */
        unsigned long long usage;
+       /*
+        * the maximal value of the usage from the counter creation
+        */
+       unsigned long long max_usage;
        /*
         * the limit that usage cannot exceed
         */
@@ -39,8 +45,9 @@ struct res_counter {
        spinlock_t lock;
 };
 
-/*
+/**
  * Helpers to interact with userspace
+ * res_counter_read_u64() - returns the value of the specified member.
  * res_counter_read/_write - put/get the specified fields from the
  * res_counter struct to/from the user
  *
@@ -51,6 +58,8 @@ struct res_counter {
  * @pos:     and the offset.
  */
 
+u64 res_counter_read_u64(struct res_counter *counter, int member);
+
 ssize_t res_counter_read(struct res_counter *counter, int member,
                const char __user *buf, size_t nbytes, loff_t *pos,
                int (*read_strategy)(unsigned long long val, char *s));
@@ -64,6 +73,7 @@ ssize_t res_counter_write(struct res_counter *counter, int member,
 
 enum {
        RES_USAGE,
+       RES_MAX_USAGE,
        RES_LIMIT,
        RES_FAILCNT,
 };
@@ -124,4 +134,21 @@ static inline bool res_counter_check_under_limit(struct res_counter *cnt)
        return ret;
 }
 
+static inline void res_counter_reset_max(struct res_counter *cnt)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&cnt->lock, flags);
+       cnt->max_usage = cnt->usage;
+       spin_unlock_irqrestore(&cnt->lock, flags);
+}
+
+static inline void res_counter_reset_failcnt(struct res_counter *cnt)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&cnt->lock, flags);
+       cnt->failcnt = 0;
+       spin_unlock_irqrestore(&cnt->lock, flags);
+}
 #endif
index ae13db714742a91f95e644f582e3517f5e85651e..aaa423a6f3d9167ed4cd77c23053b271d1874631 100644 (file)
@@ -19,6 +19,7 @@ struct task_struct;
 #define        RUSAGE_SELF     0
 #define        RUSAGE_CHILDREN (-1)
 #define RUSAGE_BOTH    (-2)            /* sys_wait4() uses this */
+#define        RUSAGE_THREAD   1               /* only the calling thread */
 
 struct rusage {
        struct timeval ru_utime;        /* user time used */
index cfb66bbc0f27db46287d76c76f0440c394d30c34..c1c99c9643d38f5373e779dcbe5211e9bec31537 100644 (file)
@@ -14,8 +14,6 @@
 #ifndef LINUX_RIO_H
 #define LINUX_RIO_H
 
-#ifdef __KERNEL__
-
 #include <linux/types.h>
 #include <linux/ioport.h>
 #include <linux/list.h>
@@ -331,5 +329,4 @@ 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 */
index 7adb2a1aac92603449fe1810944b2c7513a6e393..90987b7bcc1be21efcd979f9029dbecb89daf503 100644 (file)
@@ -13,8 +13,6 @@
 #ifndef LINUX_RIO_DRV_H
 #define LINUX_RIO_DRV_H
 
-#ifdef __KERNEL__
-
 #include <linux/types.h>
 #include <linux/ioport.h>
 #include <linux/list.h>
@@ -465,5 +463,4 @@ 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 */
index 7b524b4109a039a5cf065d60af824fa4d2fb0ff0..efd348fe8ca75f6d9effcf8f05e87bd276e46d97 100644 (file)
@@ -9,8 +9,6 @@
 
 #include <linux/linkage.h>
 
-#ifdef __KERNEL__
-
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <asm/system.h>
@@ -90,5 +88,4 @@ extern void up_read_non_owner(struct rw_semaphore *sem);
 # define up_read_non_owner(sem)                        up_read(sem)
 #endif
 
-#endif /* __KERNEL__ */
 #endif /* _LINUX_RWSEM_H */
index 024d72b47a0c0cc36ff2722078f66d5616418229..03c238088aee57a26fbbcd110cf10e901e918fb9 100644 (file)
@@ -554,6 +554,14 @@ struct signal_struct {
 #define SIGNAL_STOP_DEQUEUED   0x00000002 /* stop signal dequeued */
 #define SIGNAL_STOP_CONTINUED  0x00000004 /* SIGCONT since WCONTINUED reap */
 #define SIGNAL_GROUP_EXIT      0x00000008 /* group exit in progress */
+/*
+ * Pending notifications to parent.
+ */
+#define SIGNAL_CLD_STOPPED     0x00000010
+#define SIGNAL_CLD_CONTINUED   0x00000020
+#define SIGNAL_CLD_MASK                (SIGNAL_CLD_STOPPED|SIGNAL_CLD_CONTINUED)
+
+#define SIGNAL_UNKILLABLE      0x00000040 /* for init: ignore fatal signals */
 
 /* If true, all threads except ->group_exit_task have pending SIGKILL */
 static inline int signal_group_exit(const struct signal_struct *sig)
@@ -1167,7 +1175,7 @@ struct task_struct {
        struct sighand_struct *sighand;
 
        sigset_t blocked, real_blocked;
-       sigset_t saved_sigmask;         /* To be restored with TIF_RESTORE_SIGMASK */
+       sigset_t saved_sigmask; /* restored if set_restore_sigmask() was used */
        struct sigpending pending;
 
        unsigned long sas_ss_sp;
@@ -1669,7 +1677,10 @@ extern struct pid_namespace init_pid_ns;
 extern struct task_struct *find_task_by_pid_type_ns(int type, int pid,
                struct pid_namespace *ns);
 
-extern struct task_struct *find_task_by_pid(pid_t nr);
+static inline struct task_struct *__deprecated find_task_by_pid(pid_t nr)
+{
+       return find_task_by_pid_type_ns(PIDTYPE_PID, nr, &init_pid_ns);
+}
 extern struct task_struct *find_task_by_vpid(pid_t nr);
 extern struct task_struct *find_task_by_pid_ns(pid_t nr,
                struct pid_namespace *ns);
@@ -1745,8 +1756,7 @@ extern void zap_other_threads(struct task_struct *p);
 extern int kill_proc(pid_t, int, int);
 extern struct sigqueue *sigqueue_alloc(void);
 extern void sigqueue_free(struct sigqueue *);
-extern int send_sigqueue(int, struct sigqueue *,  struct task_struct *);
-extern int send_group_sigqueue(int, struct sigqueue *,  struct task_struct *);
+extern int send_sigqueue(struct sigqueue *,  struct task_struct *, int group);
 extern int do_sigaction(int, struct k_sigaction *, struct k_sigaction *);
 extern int do_sigaltstack(const stack_t __user *, stack_t __user *, unsigned long);
 
@@ -2148,6 +2158,19 @@ static inline void migration_init(void)
 #define TASK_SIZE_OF(tsk)      TASK_SIZE
 #endif
 
+#ifdef CONFIG_MM_OWNER
+extern void mm_update_next_owner(struct mm_struct *mm);
+extern void mm_init_owner(struct mm_struct *mm, struct task_struct *p);
+#else
+static inline void mm_update_next_owner(struct mm_struct *mm)
+{
+}
+
+static inline void mm_init_owner(struct mm_struct *mm, struct task_struct *p)
+{
+}
+#endif /* CONFIG_MM_OWNER */
+
 #endif /* __KERNEL__ */
 
 #endif
index d0a28fd1747a30cea6965d175f7fa6cfef95f13d..50737c70e78ea41e2a2e4551b6044df86f8a1de3 100644 (file)
@@ -53,8 +53,9 @@ extern void cap_capset_set(struct task_struct *target, kernel_cap_t *effective,
 extern int cap_bprm_set_security(struct linux_binprm *bprm);
 extern void cap_bprm_apply_creds(struct linux_binprm *bprm, int unsafe);
 extern int cap_bprm_secureexec(struct linux_binprm *bprm);
-extern int cap_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags);
-extern int cap_inode_removexattr(struct dentry *dentry, char *name);
+extern int cap_inode_setxattr(struct dentry *dentry, const char *name,
+                             const void *value, size_t size, int flags);
+extern int cap_inode_removexattr(struct dentry *dentry, const char *name);
 extern int cap_inode_need_killpriv(struct dentry *dentry);
 extern int cap_inode_killpriv(struct dentry *dentry);
 extern int cap_task_post_setuid(uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
@@ -1008,6 +1009,17 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *     @perm describes the combination of permissions required of this key.
  *     Return 1 if permission granted, 0 if permission denied and -ve it the
  *     normal permissions model should be effected.
+ * @key_getsecurity:
+ *     Get a textual representation of the security context attached to a key
+ *     for the purposes of honouring KEYCTL_GETSECURITY.  This function
+ *     allocates the storage for the NUL-terminated string and the caller
+ *     should free it.
+ *     @key points to the key to be queried.
+ *     @_buffer points to a pointer that should be set to point to the
+ *      resulting string (if no label or an error occurs).
+ *     Return the length of the string (including terminating NUL) or -ve if
+ *      an error.
+ *     May also return 0 (and a NULL buffer pointer) if there is no label.
  *
  * Security hooks affecting all System V IPC operations.
  *
@@ -1362,13 +1374,13 @@ struct security_operations {
        int (*inode_setattr)    (struct dentry *dentry, struct iattr *attr);
        int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
        void (*inode_delete) (struct inode *inode);
-       int (*inode_setxattr) (struct dentry *dentry, char *name, void *value,
-                              size_t size, int flags);
-       void (*inode_post_setxattr) (struct dentry *dentry, char *name, void *value,
-                                    size_t size, int flags);
-       int (*inode_getxattr) (struct dentry *dentry, char *name);
+       int (*inode_setxattr) (struct dentry *dentry, const char *name,
+                              const void *value, size_t size, int flags);
+       void (*inode_post_setxattr) (struct dentry *dentry, const char *name,
+                                    const void *value, size_t size, int flags);
+       int (*inode_getxattr) (struct dentry *dentry, const char *name);
        int (*inode_listxattr) (struct dentry *dentry);
-       int (*inode_removexattr) (struct dentry *dentry, char *name);
+       int (*inode_removexattr) (struct dentry *dentry, const char *name);
        int (*inode_need_killpriv) (struct dentry *dentry);
        int (*inode_killpriv) (struct dentry *dentry);
        int (*inode_getsecurity) (const struct inode *inode, const char *name, void **buffer, bool alloc);
@@ -1469,7 +1481,7 @@ struct security_operations {
        int (*getprocattr) (struct task_struct *p, char *name, char **value);
        int (*setprocattr) (struct task_struct *p, char *name, void *value, size_t size);
        int (*secid_to_secctx) (u32 secid, char **secdata, u32 *seclen);
-       int (*secctx_to_secid) (char *secdata, u32 seclen, u32 *secid);
+       int (*secctx_to_secid) (const char *secdata, u32 seclen, u32 *secid);
        void (*release_secctx) (char *secdata, u32 seclen);
 
 #ifdef CONFIG_SECURITY_NETWORK
@@ -1537,7 +1549,7 @@ struct security_operations {
        int (*key_permission) (key_ref_t key_ref,
                               struct task_struct *context,
                               key_perm_t perm);
-
+       int (*key_getsecurity)(struct key *key, char **_buffer);
 #endif /* CONFIG_KEYS */
 
 #ifdef CONFIG_AUDIT
@@ -1633,13 +1645,13 @@ int security_inode_permission(struct inode *inode, int mask, struct nameidata *n
 int security_inode_setattr(struct dentry *dentry, struct iattr *attr);
 int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
 void security_inode_delete(struct inode *inode);
-int security_inode_setxattr(struct dentry *dentry, char *name,
-                           void *value, size_t size, int flags);
-void security_inode_post_setxattr(struct dentry *dentry, char *name,
-                                 void *value, size_t size, int flags);
-int security_inode_getxattr(struct dentry *dentry, char *name);
+int security_inode_setxattr(struct dentry *dentry, const char *name,
+                           const void *value, size_t size, int flags);
+void security_inode_post_setxattr(struct dentry *dentry, const char *name,
+                                 const void *value, size_t size, int flags);
+int security_inode_getxattr(struct dentry *dentry, const char *name);
 int security_inode_listxattr(struct dentry *dentry);
-int security_inode_removexattr(struct dentry *dentry, char *name);
+int security_inode_removexattr(struct dentry *dentry, const char *name);
 int security_inode_need_killpriv(struct dentry *dentry);
 int security_inode_killpriv(struct dentry *dentry);
 int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc);
@@ -1718,7 +1730,7 @@ int security_setprocattr(struct task_struct *p, char *name, void *value, size_t
 int security_netlink_send(struct sock *sk, struct sk_buff *skb);
 int security_netlink_recv(struct sk_buff *skb, int cap);
 int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
-int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid);
+int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
 void security_release_secctx(char *secdata, u32 seclen);
 
 #else /* CONFIG_SECURITY */
@@ -2041,17 +2053,18 @@ static inline int security_inode_getattr(struct vfsmount *mnt,
 static inline void security_inode_delete(struct inode *inode)
 { }
 
-static inline int security_inode_setxattr(struct dentry *dentry, char *name,
-                                          void *value, size_t size, int flags)
+static inline int security_inode_setxattr(struct dentry *dentry,
+               const char *name, const void *value, size_t size, int flags)
 {
        return cap_inode_setxattr(dentry, name, value, size, flags);
 }
 
-static inline void security_inode_post_setxattr(struct dentry *dentry, char *name,
-                                                void *value, size_t size, int flags)
+static inline void security_inode_post_setxattr(struct dentry *dentry,
+               const char *name, const void *value, size_t size, int flags)
 { }
 
-static inline int security_inode_getxattr(struct dentry *dentry, char *name)
+static inline int security_inode_getxattr(struct dentry *dentry,
+                       const char *name)
 {
        return 0;
 }
@@ -2061,7 +2074,8 @@ static inline int security_inode_listxattr(struct dentry *dentry)
        return 0;
 }
 
-static inline int security_inode_removexattr(struct dentry *dentry, char *name)
+static inline int security_inode_removexattr(struct dentry *dentry,
+                       const char *name)
 {
        return cap_inode_removexattr(dentry, name);
 }
@@ -2435,7 +2449,7 @@ static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *secle
        return -EOPNOTSUPP;
 }
 
-static inline int security_secctx_to_secid(char *secdata,
+static inline int security_secctx_to_secid(const char *secdata,
                                           u32 seclen,
                                           u32 *secid)
 {
@@ -2729,6 +2743,7 @@ int security_key_alloc(struct key *key, struct task_struct *tsk, unsigned long f
 void security_key_free(struct key *key);
 int security_key_permission(key_ref_t key_ref,
                            struct task_struct *context, key_perm_t perm);
+int security_key_getsecurity(struct key *key, char **_buffer);
 
 #else
 
@@ -2750,6 +2765,12 @@ static inline int security_key_permission(key_ref_t key_ref,
        return 0;
 }
 
+static inline int security_key_getsecurity(struct key *key, char **_buffer)
+{
+       *_buffer = NULL;
+       return 0;
+}
+
 #endif
 #endif /* CONFIG_KEYS */
 
index 5b5369c3c209c66c904f2a505e1bdaf8e0cbac56..a66304a09955b0d36e7b7f67193657a444355e77 100644 (file)
@@ -1,6 +1,5 @@
 #ifndef _LINUX_SEQ_FILE_H
 #define _LINUX_SEQ_FILE_H
-#ifdef __KERNEL__
 
 #include <linux/types.h>
 #include <linux/string.h>
@@ -69,4 +68,3 @@ extern struct list_head *seq_list_next(void *v, struct list_head *head,
                loff_t *ppos);
 
 #endif
-#endif
index 7cb094a82456cbe7a6c3409013bf98d16dd9a827..d32123ae08adbc9a7ed70613c97be128d0bb5c15 100644 (file)
 /* Freescale ColdFire */
 #define PORT_MCF       78
 
-#define PORT_SC26XX    79
-
+/* Blackfin SPORT */
+#define PORT_BFIN_SPORT                79
 
 /* MN10300 on-chip UART numbers */
 #define PORT_MN10300           80
 #define PORT_MN10300_CTS       81
 
+#define PORT_SC26XX    82
+
 #ifdef __KERNEL__
 
 #include <linux/compiler.h>
index 42d2e0a948f4866533c7211c031362c8246b542a..84f997f8aa53cfcc8b04ff86bb4b0263f0e7dc1a 100644 (file)
@@ -362,8 +362,6 @@ int unhandled_signal(struct task_struct *tsk, int sig);
 #define sig_kernel_stop(sig) \
        (((sig) < SIGRTMIN) && siginmask(sig, SIG_KERNEL_STOP_MASK))
 
-#define sig_needs_tasklist(sig)        ((sig) == SIGCONT)
-
 #define sig_user_defined(t, signr) \
        (((t)->sighand->action[(signr)-1].sa.sa_handler != SIG_DFL) &&  \
         ((t)->sighand->action[(signr)-1].sa.sa_handler != SIG_IGN))
index f62caaad94e00876d7877c8cb738c95f5e61021c..805ed4b92f9a40dfd533330fb2bea5e423ed00e1 100644 (file)
@@ -9,8 +9,6 @@
 #ifndef _LINUX_SLAB_H
 #define        _LINUX_SLAB_H
 
-#ifdef __KERNEL__
-
 #include <linux/gfp.h>
 #include <linux/types.h>
 
 #define SLAB_MEM_SPREAD                0x00100000UL    /* Spread some memory over cpuset */
 #define SLAB_TRACE             0x00200000UL    /* Trace allocations and frees */
 
+/* Flag to prevent checks on free */
+#ifdef CONFIG_DEBUG_OBJECTS
+# define SLAB_DEBUG_OBJECTS    0x00400000UL
+#else
+# define SLAB_DEBUG_OBJECTS    0x00000000UL
+#endif
+
 /* The following flags affect the page allocator grouping pages by mobility */
 #define SLAB_RECLAIM_ACCOUNT   0x00020000UL            /* Objects are reclaimable */
 #define SLAB_TEMPORARY         SLAB_RECLAIM_ACCOUNT    /* Objects are short-lived */
@@ -276,5 +281,4 @@ extern const struct seq_operations slabinfo_op;
 ssize_t slabinfo_write(struct file *, const char __user *, size_t, loff_t *);
 #endif
 
-#endif /* __KERNEL__ */
 #endif /* _LINUX_SLAB_H */
index f098dff93f6bc26cd732d15b75a9ff69d894d42e..caa43b2370cb04b6b12e7aa47d398e35dbfbedb3 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/types.h>
 #include <linux/magic.h>
+#include <linux/time.h>
 
 enum smb_protocol { 
        SMB_PROTOCOL_NONE, 
index 8516954a51416ef434e46ba09db9ed88e130a647..8ccf4eca2c3d97b08a707736b885cf08c403d40d 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _LINUX_SMB_FS_I
 #define _LINUX_SMB_FS_I
 
-#ifdef __KERNEL__
 #include <linux/types.h>
 #include <linux/fs.h>
 
@@ -36,4 +35,3 @@ struct smb_inode_info {
 };
 
 #endif
-#endif
index 3aa97aa4277f3905467db75021bda4892033969e..8a060a7040d818dae9a86af3f350ea3d2635d17b 100644 (file)
@@ -9,8 +9,6 @@
 #ifndef _SMB_FS_SB
 #define _SMB_FS_SB
 
-#ifdef __KERNEL__
-
 #include <linux/types.h>
 #include <linux/smb.h>
 
@@ -96,6 +94,4 @@ smb_unlock_server(struct smb_sb_info *server)
        up(&(server->sem));
 }
 
-#endif /* __KERNEL__ */
-
 #endif
index 13ad0b82ac286a37355a321928cbcd7dd5f31944..c59a51a2b0e792c39b5de96fecf228b3bfaca244 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef _LINUX_SVGA_H
 #define _LINUX_SVGA_H
 
-#ifdef __KERNEL__
-
 #include <linux/pci.h>
 #include <video/vga.h>
 
@@ -122,6 +120,5 @@ void svga_set_timings(const struct svga_timing_regs *tm, struct fb_var_screeninf
 
 int svga_match_format(const struct svga_fb_format *frm, struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix);
 
-#endif /* __KERNEL__  */
 #endif /* _LINUX_SVGA_H */
 
index 8df6d1382ac8280b7446df8af3898ea8b0b4d588..0522f368f9d737d7f65376c8cc122cc2ea92c900 100644 (file)
@@ -240,26 +240,28 @@ asmlinkage long sys_truncate64(const char __user *path, loff_t length);
 asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length);
 #endif
 
-asmlinkage long sys_setxattr(char __user *path, char __user *name,
-                               void __user *value, size_t size, int flags);
-asmlinkage long sys_lsetxattr(char __user *path, char __user *name,
-                               void __user *value, size_t size, int flags);
-asmlinkage long sys_fsetxattr(int fd, char __user *name, void __user *value,
-                               size_t size, int flags);
-asmlinkage ssize_t sys_getxattr(char __user *path, char __user *name,
+asmlinkage long sys_setxattr(const char __user *path, const char __user *name,
+                            const void __user *value, size_t size, int flags);
+asmlinkage long sys_lsetxattr(const char __user *path, const char __user *name,
+                             const void __user *value, size_t size, int flags);
+asmlinkage long sys_fsetxattr(int fd, const char __user *name,
+                             const void __user *value, size_t size, int flags);
+asmlinkage ssize_t sys_getxattr(const char __user *path, const char __user *name,
                                void __user *value, size_t size);
-asmlinkage ssize_t sys_lgetxattr(char __user *path, char __user *name,
+asmlinkage ssize_t sys_lgetxattr(const char __user *path, const char __user *name,
                                void __user *value, size_t size);
-asmlinkage ssize_t sys_fgetxattr(int fd, char __user *name,
+asmlinkage ssize_t sys_fgetxattr(int fd, const char __user *name,
                                void __user *value, size_t size);
-asmlinkage ssize_t sys_listxattr(char __user *path, char __user *list,
+asmlinkage ssize_t sys_listxattr(const char __user *path, char __user *list,
                                size_t size);
-asmlinkage ssize_t sys_llistxattr(char __user *path, char __user *list,
+asmlinkage ssize_t sys_llistxattr(const char __user *path, char __user *list,
                                size_t size);
 asmlinkage ssize_t sys_flistxattr(int fd, char __user *list, size_t size);
-asmlinkage long sys_removexattr(char __user *path, char __user *name);
-asmlinkage long sys_lremovexattr(char __user *path, char __user *name);
-asmlinkage long sys_fremovexattr(int fd, char __user *name);
+asmlinkage long sys_removexattr(const char __user *path,
+                               const char __user *name);
+asmlinkage long sys_lremovexattr(const char __user *path,
+                                const char __user *name);
+asmlinkage long sys_fremovexattr(int fd, const char __user *name);
 
 asmlinkage unsigned long sys_brk(unsigned long brk);
 asmlinkage long sys_mprotect(unsigned long start, size_t len,
index 571f01d20a86373454000db25760f7a7aa2572da..24141b4d1a116a4523ab9085e8f830cdd26cb471 100644 (file)
@@ -945,11 +945,14 @@ enum
 /* For the /proc/sys support */
 struct ctl_table;
 struct nsproxy;
+struct ctl_table_root;
+
 extern struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev);
 extern struct ctl_table_header *__sysctl_head_next(struct nsproxy *namespaces,
                                                struct ctl_table_header *prev);
 extern void sysctl_head_finish(struct ctl_table_header *prev);
-extern int sysctl_perm(struct ctl_table *table, int op);
+extern int sysctl_perm(struct ctl_table_root *root,
+               struct ctl_table *table, int op);
 
 typedef struct ctl_table ctl_table;
 
@@ -981,11 +984,6 @@ extern int do_sysctl (int __user *name, int nlen,
                      void __user *oldval, size_t __user *oldlenp,
                      void __user *newval, size_t newlen);
 
-extern int do_sysctl_strategy (struct ctl_table *table,
-                              int __user *name, int nlen,
-                              void __user *oldval, size_t __user *oldlenp,
-                              void __user *newval, size_t newlen);
-
 extern ctl_handler sysctl_data;
 extern ctl_handler sysctl_string;
 extern ctl_handler sysctl_intvec;
@@ -1054,6 +1052,8 @@ struct ctl_table_root {
        struct list_head header_list;
        struct list_head *(*lookup)(struct ctl_table_root *root,
                                           struct nsproxy *namespaces);
+       int (*permissions)(struct ctl_table_root *root,
+                       struct nsproxy *namespaces, struct ctl_table *table);
 };
 
 /* struct ctl_table_header is used to maintain dynamic lists of
@@ -1085,8 +1085,6 @@ struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path,
 void unregister_sysctl_table(struct ctl_table_header * table);
 int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *table);
 
-#else /* __KERNEL__ */
-
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_SYSCTL_H */
index e0248631e461a960f0285d0a07ff138e80cb25d6..96411306eec63f66e3dc0afe20a169151ccbc3c6 100644 (file)
@@ -1,11 +1,7 @@
 #ifndef _LINUX_SYSV_FS_H
 #define _LINUX_SYSV_FS_H
 
-#if defined(__GNUC__)
-# define __packed2__   __attribute__((packed, aligned(2)))
-#else
->> I want to scream! <<
-#endif
+#define __packed2__    __attribute__((packed, aligned(2)))
 
 
 #ifndef __KERNEL__
index 004808a6df1d080f8389cf2a57f1d4c85ff7673d..6f371f24160b10ac57176bd2f9b3da36d01d445b 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef __LINUX_TEXTSEARCH_H
 #define __LINUX_TEXTSEARCH_H
 
-#ifdef __KERNEL__
-
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/kernel.h>
@@ -177,6 +175,4 @@ static inline void *ts_config_priv(struct ts_config *conf)
        return ((u8 *) conf + TS_PRIV_ALIGN(sizeof(struct ts_config)));
 }
 
-#endif /* __KERNEL__ */
-
 #endif
index accd7bad35b09152b8ecf2abcd8ab063c53ae5fb..38a56477f27ada34c3cd6e56c912205b066bc413 100644 (file)
@@ -92,6 +92,31 @@ static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
 #define set_need_resched()     set_thread_flag(TIF_NEED_RESCHED)
 #define clear_need_resched()   clear_thread_flag(TIF_NEED_RESCHED)
 
-#endif
+#if defined TIF_RESTORE_SIGMASK && !defined HAVE_SET_RESTORE_SIGMASK
+/*
+ * An arch can define its own version of set_restore_sigmask() to get the
+ * job done however works, with or without TIF_RESTORE_SIGMASK.
+ */
+#define HAVE_SET_RESTORE_SIGMASK       1
+
+/**
+ * set_restore_sigmask() - make sure saved_sigmask processing gets done
+ *
+ * This sets TIF_RESTORE_SIGMASK and ensures that the arch signal code
+ * will run before returning to user mode, to process the flag.  For
+ * all callers, TIF_SIGPENDING is already set or it's no harm to set
+ * it.  TIF_RESTORE_SIGMASK need not be in the set of bits that the
+ * arch code will notice on return to user mode, in case those bits
+ * are scarce.  We set TIF_SIGPENDING here to ensure that the arch
+ * signal code always gets run when TIF_RESTORE_SIGMASK is set.
+ */
+static inline void set_restore_sigmask(void)
+{
+       set_thread_flag(TIF_RESTORE_SIGMASK);
+       set_thread_flag(TIF_SIGPENDING);
+}
+#endif /* TIF_RESTORE_SIGMASK && !HAVE_SET_RESTORE_SIGMASK */
+
+#endif /* __KERNEL__ */
 
 #endif /* _LINUX_THREAD_INFO_H */
index 979fefdeb86210c15e318cc7eb8986f813181c75..d4ba79248a27fab0f33a9697deebd02bfb9440e3 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/list.h>
 #include <linux/ktime.h>
 #include <linux/stddef.h>
+#include <linux/debugobjects.h>
 
 struct tvec_base;
 
@@ -25,6 +26,7 @@ struct timer_list {
 extern struct tvec_base boot_tvec_bases;
 
 #define TIMER_INITIALIZER(_function, _expires, _data) {                \
+               .entry = { .prev = TIMER_ENTRY_STATIC },        \
                .function = (_function),                        \
                .expires = (_expires),                          \
                .data = (_data),                                \
@@ -38,6 +40,17 @@ extern struct tvec_base boot_tvec_bases;
 void init_timer(struct timer_list *timer);
 void init_timer_deferrable(struct timer_list *timer);
 
+#ifdef CONFIG_DEBUG_OBJECTS_TIMERS
+extern void init_timer_on_stack(struct timer_list *timer);
+extern void destroy_timer_on_stack(struct timer_list *timer);
+#else
+static inline void destroy_timer_on_stack(struct timer_list *timer) { }
+static inline void init_timer_on_stack(struct timer_list *timer)
+{
+       init_timer(timer);
+}
+#endif
+
 static inline void setup_timer(struct timer_list * timer,
                                void (*function)(unsigned long),
                                unsigned long data)
@@ -47,6 +60,15 @@ static inline void setup_timer(struct timer_list * timer,
        init_timer(timer);
 }
 
+static inline void setup_timer_on_stack(struct timer_list *timer,
+                                       void (*function)(unsigned long),
+                                       unsigned long data)
+{
+       timer->function = function;
+       timer->data = data;
+       init_timer_on_stack(timer);
+}
+
 /**
  * timer_pending - is a timer pending?
  * @timer: the timer in question
@@ -164,5 +186,4 @@ unsigned long __round_jiffies_relative(unsigned long j, int cpu);
 unsigned long round_jiffies(unsigned long j);
 unsigned long round_jiffies_relative(unsigned long j);
 
-
 #endif
index dd8e08fe88551a3d9c9ca2529226bfa55631e69b..7f7121f9c9687a0e5692469b3ded0d082e5f0fb7 100644 (file)
@@ -177,27 +177,33 @@ struct signal_struct;
  * size each time the window is created or resized anyway.
  *                                             - TYT, 9/14/92
  */
+
+struct tty_operations;
+
 struct tty_struct {
        int     magic;
        struct tty_driver *driver;
+       const struct tty_operations *ops;
        int index;
        struct tty_ldisc ldisc;
        struct mutex termios_mutex;
+       spinlock_t ctrl_lock;
+       /* Termios values are protected by the termios mutex */
        struct ktermios *termios, *termios_locked;
        char name[64];
-       struct pid *pgrp;
+       struct pid *pgrp;               /* Protected by ctrl lock */
        struct pid *session;
        unsigned long flags;
        int count;
-       struct winsize winsize;
+       struct winsize winsize;         /* termios mutex */
        unsigned char stopped:1, hw_stopped:1, flow_stopped:1, packet:1;
        unsigned char low_latency:1, warned:1;
-       unsigned char ctrl_status;
+       unsigned char ctrl_status;      /* ctrl_lock */
        unsigned int receive_room;      /* Bytes free for queue */
 
        struct tty_struct *link;
        struct fasync_struct *fasync;
-       struct tty_bufhead buf;
+       struct tty_bufhead buf;         /* Locked internally */
        int alt_speed;          /* For magic substitution of 38400 bps */
        wait_queue_head_t write_wait;
        wait_queue_head_t read_wait;
@@ -211,6 +217,7 @@ struct tty_struct {
        /*
         * The following is data for the N_TTY line discipline.  For
         * historical reasons, this is included in the tty structure.
+        * Mostly locked by the BKL.
         */
        unsigned int column;
        unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1;
@@ -292,15 +299,21 @@ extern void tty_unregister_device(struct tty_driver *driver, unsigned index);
 extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
                             int buflen);
 extern void tty_write_message(struct tty_struct *tty, char *msg);
+extern int tty_put_char(struct tty_struct *tty, unsigned char c);
+extern int tty_chars_in_buffer(struct tty_struct *tty);
+extern int tty_write_room(struct tty_struct *tty);
+extern void tty_driver_flush_buffer(struct tty_struct *tty);
+extern void tty_throttle(struct tty_struct *tty);
+extern void tty_unthrottle(struct tty_struct *tty);
 
 extern int is_current_pgrp_orphaned(void);
+extern struct pid *tty_get_pgrp(struct tty_struct *tty);
 extern int is_ignored(int sig);
 extern int tty_signal(int sig, struct tty_struct *tty);
 extern void tty_hangup(struct tty_struct * tty);
 extern void tty_vhangup(struct tty_struct * tty);
 extern void tty_unhangup(struct file *filp);
 extern int tty_hung_up_p(struct file * filp);
-extern int is_tty(struct file *filp);
 extern void do_SAK(struct tty_struct *tty);
 extern void __do_SAK(struct tty_struct *tty);
 extern void disassociate_ctty(int priv);
@@ -324,8 +337,7 @@ extern void tty_ldisc_put(int);
 extern void tty_wakeup(struct tty_struct *tty);
 extern void tty_ldisc_flush(struct tty_struct *tty);
 
-extern int tty_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-                    unsigned long arg);
+extern long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 extern int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
                        unsigned int cmd, unsigned long arg);
 extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg);
@@ -351,8 +363,7 @@ extern void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
 extern void tty_audit_exit(void);
 extern void tty_audit_fork(struct signal_struct *sig);
 extern void tty_audit_push(struct tty_struct *tty);
-extern void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid);
-extern void tty_audit_opening(void);
+extern void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid, u32 sessionid);
 #else
 static inline void tty_audit_add_data(struct tty_struct *tty,
                                      unsigned char *data, size_t size)
@@ -367,10 +378,7 @@ static inline void tty_audit_fork(struct signal_struct *sig)
 static inline void tty_audit_push(struct tty_struct *tty)
 {
 }
-static inline void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
-{
-}
-static inline void tty_audit_opening(void)
+static inline void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid, u32 sessionid)
 {
 }
 #endif
index 21f69aca45053c2a538d55ce19d685619cbcfc4f..59f1c0bd8f9c6f8734a1320185a3eb28a9b29990 100644 (file)
  *     This routine is called when a particular tty device is opened.
  *     This routine is mandatory; if this routine is not filled in,
  *     the attempted open will fail with ENODEV.
+ *
+ *     Required method.
  *     
  * void (*close)(struct tty_struct * tty, struct file * filp);
  *
  *     This routine is called when a particular tty device is closed.
  *
+ *     Required method.
+ *
  * int (*write)(struct tty_struct * tty,
  *              const unsigned char *buf, int count);
  *
@@ -26,7 +30,9 @@
  *     number of characters actually accepted for writing.  This
  *     routine is mandatory.
  *
- * void (*put_char)(struct tty_struct *tty, unsigned char ch);
+ *     Optional: Required for writable devices.
+ *
+ * int (*put_char)(struct tty_struct *tty, unsigned char ch);
  *
  *     This routine is called by the kernel to write a single
  *     character to the tty device.  If the kernel uses this routine,
  *     done stuffing characters into the driver.  If there is no room
  *     in the queue, the character is ignored.
  *
+ *     Optional: Kernel will use the write method if not provided.
+ *
+ *     Note: Do not call this function directly, call tty_put_char
+ *
  * void (*flush_chars)(struct tty_struct *tty);
  *
  *     This routine is called by the kernel after it has written a
  *     series of characters to the tty device using put_char().  
+ *
+ *     Optional:
+ *
+ *     Note: Do not call this function directly, call tty_driver_flush_chars
  * 
  * int  (*write_room)(struct tty_struct *tty);
  *
  *     will accept for queuing to be written.  This number is subject
  *     to change as output buffers get emptied, or if the output flow
  *     control is acted.
+ *
+ *     Required if write method is provided else not needed.
+ *
+ *     Note: Do not call this function directly, call tty_write_room
  * 
  * int  (*ioctl)(struct tty_struct *tty, struct file * file,
  *         unsigned int cmd, unsigned long arg);
  *     device-specific ioctl's.  If the ioctl number passed in cmd
  *     is not recognized by the driver, it should return ENOIOCTLCMD.
  *
+ *     Optional
+ *
  * long (*compat_ioctl)(struct tty_struct *tty, struct file * file,
  *                     unsigned int cmd, unsigned long arg);
  *
  *     implement ioctl processing for 32 bit process on 64 bit system
+ *
+ *     Optional
  * 
  * void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
  *
  *     This routine allows the tty driver to be notified when
- *     device's termios settings have changed.  Note that a
- *     well-designed tty driver should be prepared to accept the case
- *     where old == NULL, and try to do something rational.
+ *     device's termios settings have changed.
+ *
+ *     Optional: Called under the termios lock
+ *
  *
  * void (*set_ldisc)(struct tty_struct *tty);
  *
  *     This routine allows the tty driver to be notified when the
  *     device's termios settings have changed.
+ *
+ *     Optional: Called under BKL (currently)
  * 
  * void (*throttle)(struct tty_struct * tty);
  *
  *     This routine notifies the tty driver that input buffers for
  *     the line discipline are close to full, and it should somehow
  *     signal that no more characters should be sent to the tty.
+ *
+ *     Optional: Always invoke via tty_throttle();
  * 
  * void (*unthrottle)(struct tty_struct * tty);
  *
  *     that characters can now be sent to the tty without fear of
  *     overrunning the input buffers of the line disciplines.
  * 
+ *     Optional: Always invoke via tty_unthrottle();
+ *
  * void (*stop)(struct tty_struct *tty);
  *
  *     This routine notifies the tty driver that it should stop
  *     outputting characters to the tty device.  
+ *
+ *     Optional:
+ *
+ *     Note: Call stop_tty not this method.
  * 
  * void (*start)(struct tty_struct *tty);
  *
  *     This routine notifies the tty driver that it resume sending
  *     characters to the tty device.
+ *
+ *     Optional:
+ *
+ *     Note: Call start_tty not this method.
  * 
  * void (*hangup)(struct tty_struct *tty);
  *
  *     This routine notifies the tty driver that it should hangup the
  *     tty device.
  *
+ *     Required:
+ *
  * void (*break_ctl)(struct tty_stuct *tty, int state);
  *
  *     This optional routine requests the tty driver to turn on or
  *
  *     If this routine is implemented, the high-level tty driver will
  *     handle the following ioctls: TCSBRK, TCSBRKP, TIOCSBRK,
- *     TIOCCBRK.  Otherwise, these ioctls will be passed down to the
- *     driver to handle.
+ *     TIOCCBRK.
+ *
+ *     Optional: Required for TCSBRK/BRKP/etc handling.
  *
  * void (*wait_until_sent)(struct tty_struct *tty, int timeout);
  * 
  *     This routine waits until the device has written out all of the
  *     characters in its transmitter FIFO.
  *
+ *     Optional: If not provided the device is assumed to have no FIFO
+ *
+ *     Note: Usually correct to call tty_wait_until_sent
+ *
  * void (*send_xchar)(struct tty_struct *tty, char ch);
  *
  *     This routine is used to send a high-priority XON/XOFF
  *     character to the device.
+ *
+ *     Optional: If not provided then the write method is called under
+ *     the atomic write lock to keep it serialized with the ldisc.
  */
 
 #include <linux/fs.h>
@@ -132,7 +179,7 @@ struct tty_operations {
        void (*close)(struct tty_struct * tty, struct file * filp);
        int  (*write)(struct tty_struct * tty,
                      const unsigned char *buf, int count);
-       void (*put_char)(struct tty_struct *tty, unsigned char ch);
+       int  (*put_char)(struct tty_struct *tty, unsigned char ch);
        void (*flush_chars)(struct tty_struct *tty);
        int  (*write_room)(struct tty_struct *tty);
        int  (*chars_in_buffer)(struct tty_struct *tty);
@@ -153,8 +200,6 @@ struct tty_operations {
        void (*send_xchar)(struct tty_struct *tty, char ch);
        int (*read_proc)(char *page, char **start, off_t off,
                          int count, int *eof, void *data);
-       int (*write_proc)(struct file *file, const char __user *buffer,
-                         unsigned long count, void *data);
        int (*tiocmget)(struct tty_struct *tty, struct file *file);
        int (*tiocmset)(struct tty_struct *tty, struct file *file,
                        unsigned int set, unsigned int clear);
@@ -190,48 +235,13 @@ struct tty_driver {
        struct tty_struct **ttys;
        struct ktermios **termios;
        struct ktermios **termios_locked;
-       void *driver_state;     /* only used for the PTY driver */
-       
+       void *driver_state;
+
        /*
-        * Interface routines from the upper tty layer to the tty
-        * driver.      Will be replaced with struct tty_operations.
+        * Driver methods
         */
-       int  (*open)(struct tty_struct * tty, struct file * filp);
-       void (*close)(struct tty_struct * tty, struct file * filp);
-       int  (*write)(struct tty_struct * tty,
-                     const unsigned char *buf, int count);
-       void (*put_char)(struct tty_struct *tty, unsigned char ch);
-       void (*flush_chars)(struct tty_struct *tty);
-       int  (*write_room)(struct tty_struct *tty);
-       int  (*chars_in_buffer)(struct tty_struct *tty);
-       int  (*ioctl)(struct tty_struct *tty, struct file * file,
-                   unsigned int cmd, unsigned long arg);
-       long (*compat_ioctl)(struct tty_struct *tty, struct file * file,
-                            unsigned int cmd, unsigned long arg);
-       void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
-       void (*throttle)(struct tty_struct * tty);
-       void (*unthrottle)(struct tty_struct * tty);
-       void (*stop)(struct tty_struct *tty);
-       void (*start)(struct tty_struct *tty);
-       void (*hangup)(struct tty_struct *tty);
-       void (*break_ctl)(struct tty_struct *tty, int state);
-       void (*flush_buffer)(struct tty_struct *tty);
-       void (*set_ldisc)(struct tty_struct *tty);
-       void (*wait_until_sent)(struct tty_struct *tty, int timeout);
-       void (*send_xchar)(struct tty_struct *tty, char ch);
-       int (*read_proc)(char *page, char **start, off_t off,
-                         int count, int *eof, void *data);
-       int (*write_proc)(struct file *file, const char __user *buffer,
-                         unsigned long count, void *data);
-       int (*tiocmget)(struct tty_struct *tty, struct file *file);
-       int (*tiocmset)(struct tty_struct *tty, struct file *file,
-                       unsigned int set, unsigned int clear);
-#ifdef CONFIG_CONSOLE_POLL
-       int (*poll_init)(struct tty_driver *driver, int line, char *options);
-       int (*poll_get_char)(struct tty_driver *driver, int line);
-       void (*poll_put_char)(struct tty_driver *driver, int line, char ch);
-#endif
 
+       const struct tty_operations *ops;
        struct list_head tty_drivers;
 };
 
diff --git a/include/linux/unaligned/access_ok.h b/include/linux/unaligned/access_ok.h
new file mode 100644 (file)
index 0000000..99c1b4d
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef _LINUX_UNALIGNED_ACCESS_OK_H
+#define _LINUX_UNALIGNED_ACCESS_OK_H
+
+#include <linux/kernel.h>
+#include <asm/byteorder.h>
+
+static inline u16 get_unaligned_le16(const void *p)
+{
+       return le16_to_cpup((__le16 *)p);
+}
+
+static inline u32 get_unaligned_le32(const void *p)
+{
+       return le32_to_cpup((__le32 *)p);
+}
+
+static inline u64 get_unaligned_le64(const void *p)
+{
+       return le64_to_cpup((__le64 *)p);
+}
+
+static inline u16 get_unaligned_be16(const void *p)
+{
+       return be16_to_cpup((__be16 *)p);
+}
+
+static inline u32 get_unaligned_be32(const void *p)
+{
+       return be32_to_cpup((__be32 *)p);
+}
+
+static inline u64 get_unaligned_be64(const void *p)
+{
+       return be64_to_cpup((__be64 *)p);
+}
+
+static inline void put_unaligned_le16(u16 val, void *p)
+{
+       *((__le16 *)p) = cpu_to_le16(val);
+}
+
+static inline void put_unaligned_le32(u32 val, void *p)
+{
+       *((__le32 *)p) = cpu_to_le32(val);
+}
+
+static inline void put_unaligned_le64(u64 val, void *p)
+{
+       *((__le64 *)p) = cpu_to_le64(val);
+}
+
+static inline void put_unaligned_be16(u16 val, void *p)
+{
+       *((__be16 *)p) = cpu_to_be16(val);
+}
+
+static inline void put_unaligned_be32(u32 val, void *p)
+{
+       *((__be32 *)p) = cpu_to_be32(val);
+}
+
+static inline void put_unaligned_be64(u64 val, void *p)
+{
+       *((__be64 *)p) = cpu_to_be64(val);
+}
+
+#endif /* _LINUX_UNALIGNED_ACCESS_OK_H */
diff --git a/include/linux/unaligned/be_byteshift.h b/include/linux/unaligned/be_byteshift.h
new file mode 100644 (file)
index 0000000..46dd12c
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef _LINUX_UNALIGNED_BE_BYTESHIFT_H
+#define _LINUX_UNALIGNED_BE_BYTESHIFT_H
+
+#include <linux/kernel.h>
+
+static inline u16 __get_unaligned_be16(const u8 *p)
+{
+       return p[0] << 8 | p[1];
+}
+
+static inline u32 __get_unaligned_be32(const u8 *p)
+{
+       return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
+}
+
+static inline u64 __get_unaligned_be64(const u8 *p)
+{
+       return (u64)__get_unaligned_be32(p) << 32 |
+              __get_unaligned_be32(p + 4);
+}
+
+static inline void __put_unaligned_be16(u16 val, u8 *p)
+{
+       *p++ = val >> 8;
+       *p++ = val;
+}
+
+static inline void __put_unaligned_be32(u32 val, u8 *p)
+{
+       __put_unaligned_be16(val >> 16, p);
+       __put_unaligned_be16(val, p + 2);
+}
+
+static inline void __put_unaligned_be64(u64 val, u8 *p)
+{
+       __put_unaligned_be32(val >> 32, p);
+       __put_unaligned_be32(val, p + 4);
+}
+
+static inline u16 get_unaligned_be16(const void *p)
+{
+       return __get_unaligned_be16((const u8 *)p);
+}
+
+static inline u32 get_unaligned_be32(const void *p)
+{
+       return __get_unaligned_be32((const u8 *)p);
+}
+
+static inline u64 get_unaligned_be64(const void *p)
+{
+       return __get_unaligned_be64((const u8 *)p);
+}
+
+static inline void put_unaligned_be16(u16 val, void *p)
+{
+       __put_unaligned_be16(val, p);
+}
+
+static inline void put_unaligned_be32(u32 val, void *p)
+{
+       __put_unaligned_be32(val, p);
+}
+
+static inline void put_unaligned_be64(u64 val, void *p)
+{
+       __put_unaligned_be64(val, p);
+}
+
+#endif /* _LINUX_UNALIGNED_BE_BYTESHIFT_H */
diff --git a/include/linux/unaligned/be_memmove.h b/include/linux/unaligned/be_memmove.h
new file mode 100644 (file)
index 0000000..c2a76c5
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _LINUX_UNALIGNED_BE_MEMMOVE_H
+#define _LINUX_UNALIGNED_BE_MEMMOVE_H
+
+#include <linux/unaligned/memmove.h>
+
+static inline u16 get_unaligned_be16(const void *p)
+{
+       return __get_unaligned_memmove16((const u8 *)p);
+}
+
+static inline u32 get_unaligned_be32(const void *p)
+{
+       return __get_unaligned_memmove32((const u8 *)p);
+}
+
+static inline u64 get_unaligned_be64(const void *p)
+{
+       return __get_unaligned_memmove64((const u8 *)p);
+}
+
+static inline void put_unaligned_be16(u16 val, void *p)
+{
+       __put_unaligned_memmove16(val, p);
+}
+
+static inline void put_unaligned_be32(u32 val, void *p)
+{
+       __put_unaligned_memmove32(val, p);
+}
+
+static inline void put_unaligned_be64(u64 val, void *p)
+{
+       __put_unaligned_memmove64(val, p);
+}
+
+#endif /* _LINUX_UNALIGNED_LE_MEMMOVE_H */
diff --git a/include/linux/unaligned/be_struct.h b/include/linux/unaligned/be_struct.h
new file mode 100644 (file)
index 0000000..1324158
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _LINUX_UNALIGNED_BE_STRUCT_H
+#define _LINUX_UNALIGNED_BE_STRUCT_H
+
+#include <linux/unaligned/packed_struct.h>
+
+static inline u16 get_unaligned_be16(const void *p)
+{
+       return __get_unaligned_cpu16((const u8 *)p);
+}
+
+static inline u32 get_unaligned_be32(const void *p)
+{
+       return __get_unaligned_cpu32((const u8 *)p);
+}
+
+static inline u64 get_unaligned_be64(const void *p)
+{
+       return __get_unaligned_cpu64((const u8 *)p);
+}
+
+static inline void put_unaligned_be16(u16 val, void *p)
+{
+       __put_unaligned_cpu16(val, p);
+}
+
+static inline void put_unaligned_be32(u32 val, void *p)
+{
+       __put_unaligned_cpu32(val, p);
+}
+
+static inline void put_unaligned_be64(u64 val, void *p)
+{
+       __put_unaligned_cpu64(val, p);
+}
+
+#endif /* _LINUX_UNALIGNED_BE_STRUCT_H */
diff --git a/include/linux/unaligned/generic.h b/include/linux/unaligned/generic.h
new file mode 100644 (file)
index 0000000..02d97ff
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef _LINUX_UNALIGNED_GENERIC_H
+#define _LINUX_UNALIGNED_GENERIC_H
+
+/*
+ * Cause a link-time error if we try an unaligned access other than
+ * 1,2,4 or 8 bytes long
+ */
+extern void __bad_unaligned_access_size(void);
+
+#define __get_unaligned_le(ptr) ((__force typeof(*(ptr)))({                    \
+       __builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr),                      \
+       __builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_le16((ptr)),   \
+       __builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_le32((ptr)),   \
+       __builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_le64((ptr)),   \
+       __bad_unaligned_access_size()))));                                      \
+       }))
+
+#define __get_unaligned_be(ptr) ((__force typeof(*(ptr)))({                    \
+       __builtin_choose_expr(sizeof(*(ptr)) == 1, *(ptr),                      \
+       __builtin_choose_expr(sizeof(*(ptr)) == 2, get_unaligned_be16((ptr)),   \
+       __builtin_choose_expr(sizeof(*(ptr)) == 4, get_unaligned_be32((ptr)),   \
+       __builtin_choose_expr(sizeof(*(ptr)) == 8, get_unaligned_be64((ptr)),   \
+       __bad_unaligned_access_size()))));                                      \
+       }))
+
+#define __put_unaligned_le(val, ptr) ({                                        \
+       void *__gu_p = (ptr);                                           \
+       switch (sizeof(*(ptr))) {                                       \
+       case 1:                                                         \
+               *(u8 *)__gu_p = (__force u8)(val);                      \
+               break;                                                  \
+       case 2:                                                         \
+               put_unaligned_le16((__force u16)(val), __gu_p);         \
+               break;                                                  \
+       case 4:                                                         \
+               put_unaligned_le32((__force u32)(val), __gu_p);         \
+               break;                                                  \
+       case 8:                                                         \
+               put_unaligned_le64((__force u64)(val), __gu_p);         \
+               break;                                                  \
+       default:                                                        \
+               __bad_unaligned_access_size();                          \
+               break;                                                  \
+       }                                                               \
+       (void)0; })
+
+#define __put_unaligned_be(val, ptr) ({                                        \
+       void *__gu_p = (ptr);                                           \
+       switch (sizeof(*(ptr))) {                                       \
+       case 1:                                                         \
+               *(u8 *)__gu_p = (__force u8)(val);                      \
+               break;                                                  \
+       case 2:                                                         \
+               put_unaligned_be16((__force u16)(val), __gu_p);         \
+               break;                                                  \
+       case 4:                                                         \
+               put_unaligned_be32((__force u32)(val), __gu_p);         \
+               break;                                                  \
+       case 8:                                                         \
+               put_unaligned_be64((__force u64)(val), __gu_p);         \
+               break;                                                  \
+       default:                                                        \
+               __bad_unaligned_access_size();                          \
+               break;                                                  \
+       }                                                               \
+       (void)0; })
+
+#endif /* _LINUX_UNALIGNED_GENERIC_H */
diff --git a/include/linux/unaligned/le_byteshift.h b/include/linux/unaligned/le_byteshift.h
new file mode 100644 (file)
index 0000000..59777e9
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef _LINUX_UNALIGNED_LE_BYTESHIFT_H
+#define _LINUX_UNALIGNED_LE_BYTESHIFT_H
+
+#include <linux/kernel.h>
+
+static inline u16 __get_unaligned_le16(const u8 *p)
+{
+       return p[0] | p[1] << 8;
+}
+
+static inline u32 __get_unaligned_le32(const u8 *p)
+{
+       return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
+}
+
+static inline u64 __get_unaligned_le64(const u8 *p)
+{
+       return (u64)__get_unaligned_le32(p + 4) << 32 |
+              __get_unaligned_le32(p);
+}
+
+static inline void __put_unaligned_le16(u16 val, u8 *p)
+{
+       *p++ = val;
+       *p++ = val >> 8;
+}
+
+static inline void __put_unaligned_le32(u32 val, u8 *p)
+{
+       __put_unaligned_le16(val >> 16, p + 2);
+       __put_unaligned_le16(val, p);
+}
+
+static inline void __put_unaligned_le64(u64 val, u8 *p)
+{
+       __put_unaligned_le32(val >> 32, p + 4);
+       __put_unaligned_le32(val, p);
+}
+
+static inline u16 get_unaligned_le16(const void *p)
+{
+       return __get_unaligned_le16((const u8 *)p);
+}
+
+static inline u32 get_unaligned_le32(const void *p)
+{
+       return __get_unaligned_le32((const u8 *)p);
+}
+
+static inline u64 get_unaligned_le64(const void *p)
+{
+       return __get_unaligned_le64((const u8 *)p);
+}
+
+static inline void put_unaligned_le16(u16 val, void *p)
+{
+       __put_unaligned_le16(val, p);
+}
+
+static inline void put_unaligned_le32(u32 val, void *p)
+{
+       __put_unaligned_le32(val, p);
+}
+
+static inline void put_unaligned_le64(u64 val, void *p)
+{
+       __put_unaligned_le64(val, p);
+}
+
+#endif /* _LINUX_UNALIGNED_LE_BYTESHIFT_H */
diff --git a/include/linux/unaligned/le_memmove.h b/include/linux/unaligned/le_memmove.h
new file mode 100644 (file)
index 0000000..269849b
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _LINUX_UNALIGNED_LE_MEMMOVE_H
+#define _LINUX_UNALIGNED_LE_MEMMOVE_H
+
+#include <linux/unaligned/memmove.h>
+
+static inline u16 get_unaligned_le16(const void *p)
+{
+       return __get_unaligned_memmove16((const u8 *)p);
+}
+
+static inline u32 get_unaligned_le32(const void *p)
+{
+       return __get_unaligned_memmove32((const u8 *)p);
+}
+
+static inline u64 get_unaligned_le64(const void *p)
+{
+       return __get_unaligned_memmove64((const u8 *)p);
+}
+
+static inline void put_unaligned_le16(u16 val, void *p)
+{
+       __put_unaligned_memmove16(val, p);
+}
+
+static inline void put_unaligned_le32(u32 val, void *p)
+{
+       __put_unaligned_memmove32(val, p);
+}
+
+static inline void put_unaligned_le64(u64 val, void *p)
+{
+       __put_unaligned_memmove64(val, p);
+}
+
+#endif /* _LINUX_UNALIGNED_LE_MEMMOVE_H */
diff --git a/include/linux/unaligned/le_struct.h b/include/linux/unaligned/le_struct.h
new file mode 100644 (file)
index 0000000..088c457
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _LINUX_UNALIGNED_LE_STRUCT_H
+#define _LINUX_UNALIGNED_LE_STRUCT_H
+
+#include <linux/unaligned/packed_struct.h>
+
+static inline u16 get_unaligned_le16(const void *p)
+{
+       return __get_unaligned_cpu16((const u8 *)p);
+}
+
+static inline u32 get_unaligned_le32(const void *p)
+{
+       return __get_unaligned_cpu32((const u8 *)p);
+}
+
+static inline u64 get_unaligned_le64(const void *p)
+{
+       return __get_unaligned_cpu64((const u8 *)p);
+}
+
+static inline void put_unaligned_le16(u16 val, void *p)
+{
+       __put_unaligned_cpu16(val, p);
+}
+
+static inline void put_unaligned_le32(u32 val, void *p)
+{
+       __put_unaligned_cpu32(val, p);
+}
+
+static inline void put_unaligned_le64(u64 val, void *p)
+{
+       __put_unaligned_cpu64(val, p);
+}
+
+#endif /* _LINUX_UNALIGNED_LE_STRUCT_H */
diff --git a/include/linux/unaligned/memmove.h b/include/linux/unaligned/memmove.h
new file mode 100644 (file)
index 0000000..eeb5a77
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef _LINUX_UNALIGNED_MEMMOVE_H
+#define _LINUX_UNALIGNED_MEMMOVE_H
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
+
+static inline u16 __get_unaligned_memmove16(const void *p)
+{
+       u16 tmp;
+       memmove(&tmp, p, 2);
+       return tmp;
+}
+
+static inline u32 __get_unaligned_memmove32(const void *p)
+{
+       u32 tmp;
+       memmove(&tmp, p, 4);
+       return tmp;
+}
+
+static inline u64 __get_unaligned_memmove64(const void *p)
+{
+       u64 tmp;
+       memmove(&tmp, p, 8);
+       return tmp;
+}
+
+static inline void __put_unaligned_memmove16(u16 val, void *p)
+{
+       memmove(p, &val, 2);
+}
+
+static inline void __put_unaligned_memmove32(u32 val, void *p)
+{
+       memmove(p, &val, 4);
+}
+
+static inline void __put_unaligned_memmove64(u64 val, void *p)
+{
+       memmove(p, &val, 8);
+}
+
+#endif /* _LINUX_UNALIGNED_MEMMOVE_H */
diff --git a/include/linux/unaligned/packed_struct.h b/include/linux/unaligned/packed_struct.h
new file mode 100644 (file)
index 0000000..2498bb9
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef _LINUX_UNALIGNED_PACKED_STRUCT_H
+#define _LINUX_UNALIGNED_PACKED_STRUCT_H
+
+#include <linux/kernel.h>
+
+struct __una_u16 { u16 x __attribute__((packed)); };
+struct __una_u32 { u32 x __attribute__((packed)); };
+struct __una_u64 { u64 x __attribute__((packed)); };
+
+static inline u16 __get_unaligned_cpu16(const void *p)
+{
+       const struct __una_u16 *ptr = (const struct __una_u16 *)p;
+       return ptr->x;
+}
+
+static inline u32 __get_unaligned_cpu32(const void *p)
+{
+       const struct __una_u32 *ptr = (const struct __una_u32 *)p;
+       return ptr->x;
+}
+
+static inline u64 __get_unaligned_cpu64(const void *p)
+{
+       const struct __una_u64 *ptr = (const struct __una_u64 *)p;
+       return ptr->x;
+}
+
+static inline void __put_unaligned_cpu16(u16 val, void *p)
+{
+       struct __una_u16 *ptr = (struct __una_u16 *)p;
+       ptr->x = val;
+}
+
+static inline void __put_unaligned_cpu32(u32 val, void *p)
+{
+       struct __una_u32 *ptr = (struct __una_u32 *)p;
+       ptr->x = val;
+}
+
+static inline void __put_unaligned_cpu64(u64 val, void *p)
+{
+       struct __una_u64 *ptr = (struct __una_u64 *)p;
+       ptr->x = val;
+}
+
+#endif /* _LINUX_UNALIGNED_PACKED_STRUCT_H */
index b7b3362f7717823768d0ae30f539019048ec9571..f462439cc2886c56f7c1940f4100ba726d4068c4 100644 (file)
@@ -114,6 +114,9 @@ struct file;
 int dirty_writeback_centisecs_handler(struct ctl_table *, int, struct file *,
                                      void __user *, size_t *, loff_t *);
 
+void get_dirty_limits(long *pbackground, long *pdirty, long *pbdi_dirty,
+                struct backing_dev_info *bdi);
+
 void page_writeback_init(void);
 void balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
                                        unsigned long nr_pages_dirtied);
index df6b95d2218e26930ef95d0bee2e05187f487659..d131e352cfe1f1ec9b0157625cc2db98d1b8098a 100644 (file)
@@ -47,10 +47,10 @@ struct xattr_handler {
 };
 
 ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
-ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t);
+ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t);
 ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
-int vfs_setxattr(struct dentry *, char *, void *, size_t, int);
-int vfs_removexattr(struct dentry *, char *);
+int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int);
+int vfs_removexattr(struct dentry *, const char *);
 
 ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
 ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
index 0ea0bd85c0368543dae9bc754e7cd97dd50be61d..2a527742701a2232090cc7e35334ebac12601b9d 100644 (file)
@@ -64,6 +64,7 @@ enum {
        /* Conexant MPEG encoder/decoders: reserved range 410-420 */
        V4L2_IDENT_CX23415 = 415,
        V4L2_IDENT_CX23416 = 416,
+       V4L2_IDENT_CX23418 = 418,
 
        /* module vp27smpx: just ident 2700 */
        V4L2_IDENT_VP27SMPX = 2700,
index 316a58453134df7db59ff22d74253b73c2747f83..020d05758bd8b951a352aabc043b0312de827800 100644 (file)
@@ -107,9 +107,11 @@ int v4l2_chip_match_host(u32 id_type, u32 chip_id);
 struct i2c_driver;
 struct i2c_adapter;
 struct i2c_client;
+struct i2c_device_id;
 
 int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver *driver,
-               const char *name, int (*probe)(struct i2c_client *));
+               const char *name,
+               int (*probe)(struct i2c_client *, const struct i2c_device_id *));
 
 /* ------------------------------------------------------------------------- */
 
index e7645578fc22dbb87e817a810d3184c8f8a45d96..347b6f8beb23761fa4a7c77fa65ad1dc6a81274b 100644 (file)
@@ -25,7 +25,7 @@ struct v4l2_i2c_driver_data {
        const char * const name;
        int driverid;
        int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
-       int (*probe)(struct i2c_client *client);
+       int (*probe)(struct i2c_client *client, const struct i2c_device_id *id);
        int (*remove)(struct i2c_client *client);
        int (*suspend)(struct i2c_client *client, pm_message_t state);
        int (*resume)(struct i2c_client *client);
index 9e4bab2769151fd51eed09d77bbbb52b2a76068d..7b6f06be795034d7ae64b385bfa9ef0eac4078c9 100644 (file)
@@ -30,7 +30,7 @@ struct v4l2_i2c_driver_data {
        const char * const name;
        int driverid;
        int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
-       int (*probe)(struct i2c_client *client);
+       int (*probe)(struct i2c_client *client, const struct i2c_device_id *id);
        int (*remove)(struct i2c_client *client);
        int (*suspend)(struct i2c_client *client, pm_message_t state);
        int (*resume)(struct i2c_client *client);
index 5e53a85b5ca1bc56014a192b50304800298ae386..e4d2d6baa98388e4d673f5f57ddc20405a3fdb69 100644 (file)
@@ -103,6 +103,7 @@ struct cipso_v4_doi;
 struct netlbl_audit {
        u32 secid;
        uid_t loginuid;
+       u32 sessionid;
 };
 
 /*
index baa9f372cfd165b7496954bef31510990d4190bd..d1350bcccb03c68efb07bac000b16c0f9cb49ca1 100644 (file)
@@ -597,8 +597,9 @@ struct xfrm_spi_skb_cb {
 /* Audit Information */
 struct xfrm_audit
 {
-       u32     loginuid;
        u32     secid;
+       uid_t   loginuid;
+       u32     sessionid;
 };
 
 #ifdef CONFIG_AUDITSYSCALL
@@ -616,13 +617,13 @@ static inline struct audit_buffer *xfrm_audit_start(const char *op)
        return audit_buf;
 }
 
-static inline void xfrm_audit_helper_usrinfo(u32 auid, u32 secid,
+static inline void xfrm_audit_helper_usrinfo(uid_t auid, u32 ses, u32 secid,
                                             struct audit_buffer *audit_buf)
 {
        char *secctx;
        u32 secctx_len;
 
-       audit_log_format(audit_buf, " auid=%u", auid);
+       audit_log_format(audit_buf, " auid=%u ses=%u", auid, ses);
        if (secid != 0 &&
            security_secid_to_secctx(secid, &secctx, &secctx_len) == 0) {
                audit_log_format(audit_buf, " subj=%s", secctx);
@@ -632,13 +633,13 @@ static inline void xfrm_audit_helper_usrinfo(u32 auid, u32 secid,
 }
 
 extern void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
-                                 u32 auid, u32 secid);
+                                 u32 auid, u32 ses, u32 secid);
 extern void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result,
-                                 u32 auid, u32 secid);
+                                 u32 auid, u32 ses, u32 secid);
 extern void xfrm_audit_state_add(struct xfrm_state *x, int result,
-                                u32 auid, u32 secid);
+                                u32 auid, u32 ses, u32 secid);
 extern void xfrm_audit_state_delete(struct xfrm_state *x, int result,
-                                   u32 auid, u32 secid);
+                                   u32 auid, u32 ses, u32 secid);
 extern void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
                                             struct sk_buff *skb);
 extern void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family);
@@ -647,10 +648,10 @@ extern void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
 extern void xfrm_audit_state_icvfail(struct xfrm_state *x,
                                     struct sk_buff *skb, u8 proto);
 #else
-#define xfrm_audit_policy_add(x, r, a, s)      do { ; } while (0)
-#define xfrm_audit_policy_delete(x, r, a, s)   do { ; } while (0)
-#define xfrm_audit_state_add(x, r, a, s)       do { ; } while (0)
-#define xfrm_audit_state_delete(x, r, a, s)    do { ; } while (0)
+#define xfrm_audit_policy_add(x, r, a, se, s)  do { ; } while (0)
+#define xfrm_audit_policy_delete(x, r, a, se, s)       do { ; } while (0)
+#define xfrm_audit_state_add(x, r, a, se, s)   do { ; } while (0)
+#define xfrm_audit_state_delete(x, r, a, se, s)        do { ; } while (0)
 #define xfrm_audit_state_replay_overflow(x, s) do { ; } while (0)
 #define xfrm_audit_state_notfound_simple(s, f) do { ; } while (0)
 #define xfrm_audit_state_notfound(s, f, sp, sq)        do { ; } while (0)
index 22298423cf0b3d0e597e347de0ab376b8bbcaf24..9ee0d2e51b16e5ea04910b5cfff671bd5563aeb8 100644 (file)
@@ -62,7 +62,7 @@ struct ib_umem_chunk {
 #ifdef CONFIG_INFINIBAND_USER_MEM
 
 struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
-                           size_t size, int access);
+                           size_t size, int access, int dmasync);
 void ib_umem_release(struct ib_umem *umem);
 int ib_umem_page_count(struct ib_umem *umem);
 
@@ -72,7 +72,7 @@ int ib_umem_page_count(struct ib_umem *umem);
 
 static inline struct ib_umem *ib_umem_get(struct ib_ucontext *context,
                                          unsigned long addr, size_t size,
-                                         int access) {
+                                         int access, int dmasync) {
        return ERR_PTR(-EINVAL);
 }
 static inline void ib_umem_release(struct ib_umem *umem) { }
index 2dcbecce3f61201a13710d104bc69f746f265823..911a661b7278c08ef43d91afaceb1098b2670e15 100644 (file)
@@ -1542,6 +1542,24 @@ static inline void ib_dma_unmap_single(struct ib_device *dev,
                dma_unmap_single(dev->dma_device, addr, size, direction);
 }
 
+static inline u64 ib_dma_map_single_attrs(struct ib_device *dev,
+                                         void *cpu_addr, size_t size,
+                                         enum dma_data_direction direction,
+                                         struct dma_attrs *attrs)
+{
+       return dma_map_single_attrs(dev->dma_device, cpu_addr, size,
+                                   direction, attrs);
+}
+
+static inline void ib_dma_unmap_single_attrs(struct ib_device *dev,
+                                            u64 addr, size_t size,
+                                            enum dma_data_direction direction,
+                                            struct dma_attrs *attrs)
+{
+       return dma_unmap_single_attrs(dev->dma_device, addr, size,
+                                     direction, attrs);
+}
+
 /**
  * ib_dma_map_page - Map a physical page to DMA address
  * @dev: The device for which the dma_addr is to be created
@@ -1611,6 +1629,21 @@ static inline void ib_dma_unmap_sg(struct ib_device *dev,
                dma_unmap_sg(dev->dma_device, sg, nents, direction);
 }
 
+static inline int ib_dma_map_sg_attrs(struct ib_device *dev,
+                                     struct scatterlist *sg, int nents,
+                                     enum dma_data_direction direction,
+                                     struct dma_attrs *attrs)
+{
+       return dma_map_sg_attrs(dev->dma_device, sg, nents, direction, attrs);
+}
+
+static inline void ib_dma_unmap_sg_attrs(struct ib_device *dev,
+                                        struct scatterlist *sg, int nents,
+                                        enum dma_data_direction direction,
+                                        struct dma_attrs *attrs)
+{
+       dma_unmap_sg_attrs(dev->dma_device, sg, nents, direction, attrs);
+}
 /**
  * ib_sg_dma_address - Return the DMA address from a scatter/gather entry
  * @dev: The device for which the DMA addresses were created
index 7b90b63fb5c7cabf920d26590b8de56663dd46e6..cd3ca63d4fb1e43aa98d9b3bac64aca04033db18 100644 (file)
@@ -225,6 +225,7 @@ struct iscsi_conn {
 
        /* custom statistics */
        uint32_t                eh_abort_cnt;
+       uint32_t                fmr_unalign_cnt;
 };
 
 struct iscsi_pool {
index 68b634b75068bfe9e33573d6c1fe2d6f475a8b53..1f1d53f8830b55036dbf241bb38e227d8e121b5f 100644 (file)
@@ -50,6 +50,7 @@
 #define MPU401_INFO_INTEGRATED (1 << 2)        /* integrated h/w port */
 #define MPU401_INFO_MMIO       (1 << 3)        /* MMIO access */
 #define MPU401_INFO_TX_IRQ     (1 << 4)        /* independent TX irq */
+#define MPU401_INFO_NO_ACK     (1 << 6)        /* No ACK cmd needed */
 
 #define MPU401_MODE_BIT_INPUT          0
 #define MPU401_MODE_BIT_OUTPUT         1
index da071c4bbfb7aa179964b6dbc92606f88b87a5c4..3e7b257fc05fca6fba4d6325a3da1ae95c3f9fde 100644 (file)
@@ -259,17 +259,14 @@ config IKCONFIG_PROC
 config LOG_BUF_SHIFT
        int "Kernel log buffer size (16 => 64KB, 17 => 128KB)"
        range 12 21
-       default 17 if S390 || LOCKDEP
-       default 16 if X86_NUMAQ || IA64
-       default 15 if SMP
-       default 14
+       default 17
        help
          Select kernel log buffer size as a power of 2.
-         Defaults and Examples:
-                    17 => 128 KB for S/390
-                    16 => 64 KB for x86 NUMAQ or IA-64
-                    15 => 32 KB for SMP
-                    14 => 16 KB for uniprocessor
+         Examples:
+                    17 => 128 KB
+                    16 => 64 KB
+                    15 => 32 KB
+                    14 => 16 KB
                     13 =>  8 KB
                     12 =>  4 KB
 
@@ -284,6 +281,7 @@ config CGROUPS
 config CGROUP_DEBUG
        bool "Example debug cgroup subsystem"
        depends on CGROUPS
+       default n
        help
          This option enables a simple cgroup subsystem that
          exports useful debugging information about the cgroups
@@ -300,6 +298,13 @@ config CGROUP_NS
           for instance virtual servers and checkpoint/restart
           jobs.
 
+config CGROUP_DEVICE
+       bool "Device controller for cgroups"
+       depends on CGROUPS && EXPERIMENTAL
+       help
+         Provides a cgroup implementing whitelists for devices which
+         a process in the cgroup can mknod or open.
+
 config CPUSETS
        bool "Cpuset support"
        depends on SMP && CGROUPS
@@ -373,9 +378,13 @@ config RESOURCE_COUNTERS
           infrastructure that works with cgroups
        depends on CGROUPS
 
+config MM_OWNER
+       bool
+
 config CGROUP_MEM_RES_CTLR
        bool "Memory Resource Controller for Control Groups"
        depends on CGROUPS && RESOURCE_COUNTERS
+       select MM_OWNER
        help
          Provides a memory resource controller that manages both page cache and
          RSS memory.
@@ -388,6 +397,9 @@ config CGROUP_MEM_RES_CTLR
          Only enable when you're ok with these trade offs and really
          sure you need the memory resource controller.
 
+         This config option also selects MM_OWNER config option, which
+         could in turn add some fork/exit overhead.
+
 config SYSFS_DEPRECATED
        bool
 
@@ -538,6 +550,17 @@ config SYSCTL_SYSCALL
 
          If unsure say Y here.
 
+config SYSCTL_SYSCALL_CHECK
+       bool "Sysctl checks" if EMBEDDED
+       depends on SYSCTL_SYSCALL
+       default y
+       ---help---
+         sys_sysctl uses binary paths that have been found challenging
+         to properly maintain and use. This enables checks that help
+         you to keep things correct.
+
+         If unsure say Y here.
+
 config KALLSYMS
         bool "Load all symbols for debugging/ksymoops" if EMBEDDED
         default y
index d53fee8d8604a5514889bfcd93acee4dd882fae0..8eeeccb328c9f984812941592258ebd72e5d96e6 100644 (file)
@@ -57,7 +57,7 @@ static char __init *find_link(int major, int minor, int ino,
                        continue;
                return (*p)->name;
        }
-       q = (struct hash *)malloc(sizeof(struct hash));
+       q = kmalloc(sizeof(struct hash), GFP_KERNEL);
        if (!q)
                panic("can't allocate link hash entry");
        q->major = major;
@@ -77,7 +77,7 @@ static void __init free_hash(void)
                while (*p) {
                        q = *p;
                        *p = q->next;
-                       free(q);
+                       kfree(q);
                }
        }
 }
@@ -445,10 +445,10 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
 {
        int written;
        dry_run = check_only;
-       header_buf = malloc(110);
-       symlink_buf = malloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1);
-       name_buf = malloc(N_ALIGN(PATH_MAX));
-       window = malloc(WSIZE);
+       header_buf = kmalloc(110, GFP_KERNEL);
+       symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL);
+       name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL);
+       window = kmalloc(WSIZE, GFP_KERNEL);
        if (!window || !header_buf || !symlink_buf || !name_buf)
                panic("can't allocate buffers");
        state = Start;
@@ -484,10 +484,10 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
                buf += inptr;
                len -= inptr;
        }
-       free(window);
-       free(name_buf);
-       free(symlink_buf);
-       free(header_buf);
+       kfree(window);
+       kfree(name_buf);
+       kfree(symlink_buf);
+       kfree(header_buf);
        return message;
 }
 
index 1687b0167c4a4c458c0b7956a106fc678813c431..a87d4ca5c36c19706ee4d8eb2997c45f727f4ff1 100644 (file)
 #include <linux/unwind.h>
 #include <linux/buffer_head.h>
 #include <linux/debug_locks.h>
+#include <linux/debugobjects.h>
 #include <linux/lockdep.h>
 #include <linux/pid_namespace.h>
 #include <linux/device.h>
 #include <linux/kthread.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
+#include <linux/idr.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -458,7 +460,7 @@ static void noinline __init_refok rest_init(void)
        kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
        numa_default_policy();
        pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
-       kthreadd_task = find_task_by_pid(pid);
+       kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
        unlock_kernel();
 
        /*
@@ -542,6 +544,7 @@ asmlinkage void __init start_kernel(void)
         */
        unwind_init();
        lockdep_init();
+       debug_objects_early_init();
        cgroup_init_early();
 
        local_irq_disable();
@@ -559,6 +562,7 @@ asmlinkage void __init start_kernel(void)
        printk(KERN_NOTICE);
        printk(linux_banner);
        setup_arch(&command_line);
+       mm_init_owner(&init_mm, &init_task);
        setup_command_line(command_line);
        unwind_setup();
        setup_per_cpu_areas();
@@ -636,6 +640,8 @@ asmlinkage void __init start_kernel(void)
        enable_debug_pagealloc();
        cpu_hotplug_init();
        kmem_cache_init();
+       debug_objects_mem_init();
+       idr_init_cache();
        setup_per_cpu_pageset();
        numa_policy_init();
        if (late_time_init)
@@ -700,10 +706,8 @@ static void __init do_initcalls(void)
                int result;
 
                if (initcall_debug) {
-                       printk("Calling initcall 0x%p", *call);
-                       print_fn_descriptor_symbol(": %s()",
+                       print_fn_descriptor_symbol("calling  %s()\n",
                                        (unsigned long) *call);
-                       printk("\n");
                        t0 = ktime_get();
                }
 
@@ -713,15 +717,10 @@ static void __init do_initcalls(void)
                        t1 = ktime_get();
                        delta = ktime_sub(t1, t0);
 
-                       printk("initcall 0x%p", *call);
-                       print_fn_descriptor_symbol(": %s()",
+                       print_fn_descriptor_symbol("initcall %s()",
                                        (unsigned long) *call);
-                       printk(" returned %d.\n", result);
-
-                       printk("initcall 0x%p ran for %Ld msecs: ",
-                               *call, (unsigned long long)delta.tv64 >> 20);
-                       print_fn_descriptor_symbol("%s()\n",
-                               (unsigned long) *call);
+                       printk(" returned %d after %Ld msecs\n", result,
+                               (unsigned long long) delta.tv64 >> 20);
                }
 
                if (result && result != -ENODEV && initcall_debug) {
@@ -737,10 +736,9 @@ static void __init do_initcalls(void)
                        local_irq_enable();
                }
                if (msg) {
-                       printk(KERN_WARNING "initcall at 0x%p", *call);
-                       print_fn_descriptor_symbol(": %s()",
+                       print_fn_descriptor_symbol(KERN_WARNING "initcall %s()",
                                        (unsigned long) *call);
-                       printk(": returned with %s\n", msg);
+                       printk(" returned with %s\n", msg);
                }
        }
 
@@ -807,6 +805,8 @@ static int noinline init_post(void)
        (void) sys_dup(0);
        (void) sys_dup(0);
 
+       current->signal->flags |= SIGNAL_UNKILLABLE;
+
        if (ramdisk_execute_command) {
                run_init_process(ramdisk_execute_command);
                printk(KERN_WARNING "Failed to execute %s\n",
index 5fc5e33ea047c9f46b18948d06e0133733dba8dc..65c384395801aa2e9f19ec318735b9dc35c44c42 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 obj-$(CONFIG_SYSVIPC_COMPAT) += compat.o
-obj-$(CONFIG_SYSVIPC) += util.o msgutil.o msg.o sem.o shm.o
+obj-$(CONFIG_SYSVIPC) += util.o msgutil.o msg.o sem.o shm.o ipcns_notifier.o
 obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o
 obj_mq-$(CONFIG_COMPAT) += compat_mq.o
 obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y)
index 7f4235bed51bd92323cc6807ca68171c283633e2..d3497465cc0a5aa461dabce18b0f7af4dc537cea 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/sysctl.h>
 #include <linux/uaccess.h>
 #include <linux/ipc_namespace.h>
+#include <linux/msg.h>
+#include "util.h"
 
 static void *get_ipc(ctl_table *table)
 {
@@ -24,6 +26,27 @@ static void *get_ipc(ctl_table *table)
        return which;
 }
 
+/*
+ * Routine that is called when a tunable has successfully been changed by
+ * hand and it has a callback routine registered on the ipc namespace notifier
+ * chain: we don't want such tunables to be recomputed anymore upon memory
+ * add/remove or ipc namespace creation/removal.
+ * They can come back to a recomputable state by being set to a <0 value.
+ */
+static void tunable_set_callback(int val)
+{
+       if (val >= 0)
+               unregister_ipcns_notifier(current->nsproxy->ipc_ns);
+       else {
+               /*
+                * Re-enable automatic recomputing only if not already
+                * enabled.
+                */
+               recompute_msgmni(current->nsproxy->ipc_ns);
+               cond_register_ipcns_notifier(current->nsproxy->ipc_ns);
+       }
+}
+
 #ifdef CONFIG_PROC_FS
 static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
        void __user *buffer, size_t *lenp, loff_t *ppos)
@@ -35,6 +58,24 @@ static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
        return proc_dointvec(&ipc_table, write, filp, buffer, lenp, ppos);
 }
 
+static int proc_ipc_callback_dointvec(ctl_table *table, int write,
+       struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       struct ctl_table ipc_table;
+       size_t lenp_bef = *lenp;
+       int rc;
+
+       memcpy(&ipc_table, table, sizeof(ipc_table));
+       ipc_table.data = get_ipc(table);
+
+       rc = proc_dointvec(&ipc_table, write, filp, buffer, lenp, ppos);
+
+       if (write && !rc && lenp_bef == *lenp)
+               tunable_set_callback(*((int *)(ipc_table.data)));
+
+       return rc;
+}
+
 static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
        struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -49,6 +90,7 @@ static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
 #else
 #define proc_ipc_doulongvec_minmax NULL
 #define proc_ipc_dointvec         NULL
+#define proc_ipc_callback_dointvec NULL
 #endif
 
 #ifdef CONFIG_SYSCTL_SYSCALL
@@ -90,8 +132,30 @@ static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
        }
        return 1;
 }
+
+static int sysctl_ipc_registered_data(ctl_table *table, int __user *name,
+               int nlen, void __user *oldval, size_t __user *oldlenp,
+               void __user *newval, size_t newlen)
+{
+       int rc;
+
+       rc = sysctl_ipc_data(table, name, nlen, oldval, oldlenp, newval,
+               newlen);
+
+       if (newval && newlen && rc > 0) {
+               /*
+                * Tunable has successfully been changed from userland
+                */
+               int *data = get_ipc(table);
+
+               tunable_set_callback(*data);
+       }
+
+       return rc;
+}
 #else
 #define sysctl_ipc_data NULL
+#define sysctl_ipc_registered_data NULL
 #endif
 
 static struct ctl_table ipc_kern_table[] = {
@@ -137,8 +201,8 @@ static struct ctl_table ipc_kern_table[] = {
                .data           = &init_ipc_ns.msg_ctlmni,
                .maxlen         = sizeof (init_ipc_ns.msg_ctlmni),
                .mode           = 0644,
-               .proc_handler   = proc_ipc_dointvec,
-               .strategy       = sysctl_ipc_data,
+               .proc_handler   = proc_ipc_callback_dointvec,
+               .strategy       = sysctl_ipc_registered_data,
        },
        {
                .ctl_name       = KERN_MSGMNB,
diff --git a/ipc/ipcns_notifier.c b/ipc/ipcns_notifier.c
new file mode 100644 (file)
index 0000000..70ff091
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * linux/ipc/ipcns_notifier.c
+ * Copyright (C) 2007 BULL SA. Nadia Derbey
+ *
+ * Notification mechanism for ipc namespaces:
+ * The callback routine registered in the memory chain invokes the ipcns
+ * notifier chain with the IPCNS_MEMCHANGED event.
+ * Each callback routine registered in the ipcns namespace recomputes msgmni
+ * for the owning namespace.
+ */
+
+#include <linux/msg.h>
+#include <linux/rcupdate.h>
+#include <linux/notifier.h>
+#include <linux/nsproxy.h>
+#include <linux/ipc_namespace.h>
+
+#include "util.h"
+
+
+
+static BLOCKING_NOTIFIER_HEAD(ipcns_chain);
+
+
+static int ipcns_callback(struct notifier_block *self,
+                               unsigned long action, void *arg)
+{
+       struct ipc_namespace *ns;
+
+       switch (action) {
+       case IPCNS_MEMCHANGED:   /* amount of lowmem has changed */
+       case IPCNS_CREATED:
+       case IPCNS_REMOVED:
+               /*
+                * It's time to recompute msgmni
+                */
+               ns = container_of(self, struct ipc_namespace, ipcns_nb);
+               /*
+                * No need to get a reference on the ns: the 1st job of
+                * free_ipc_ns() is to unregister the callback routine.
+                * blocking_notifier_chain_unregister takes the wr lock to do
+                * it.
+                * When this callback routine is called the rd lock is held by
+                * blocking_notifier_call_chain.
+                * So the ipc ns cannot be freed while we are here.
+                */
+               recompute_msgmni(ns);
+               break;
+       default:
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+int register_ipcns_notifier(struct ipc_namespace *ns)
+{
+       memset(&ns->ipcns_nb, 0, sizeof(ns->ipcns_nb));
+       ns->ipcns_nb.notifier_call = ipcns_callback;
+       ns->ipcns_nb.priority = IPCNS_CALLBACK_PRI;
+       return blocking_notifier_chain_register(&ipcns_chain, &ns->ipcns_nb);
+}
+
+int cond_register_ipcns_notifier(struct ipc_namespace *ns)
+{
+       memset(&ns->ipcns_nb, 0, sizeof(ns->ipcns_nb));
+       ns->ipcns_nb.notifier_call = ipcns_callback;
+       ns->ipcns_nb.priority = IPCNS_CALLBACK_PRI;
+       return blocking_notifier_chain_cond_register(&ipcns_chain,
+                                                       &ns->ipcns_nb);
+}
+
+int unregister_ipcns_notifier(struct ipc_namespace *ns)
+{
+       return blocking_notifier_chain_unregister(&ipcns_chain,
+                                               &ns->ipcns_nb);
+}
+
+int ipcns_notify(unsigned long val)
+{
+       return blocking_notifier_call_chain(&ipcns_chain, val, NULL);
+}
index 46585a05473eceb84f23c456e0f7dc96ab0bfbf6..32494e8cc7a5cd5fa72b874da80c149f007e84cb 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -27,6 +27,7 @@
 #include <linux/msg.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>
+#include <linux/mm.h>
 #include <linux/proc_fs.h>
 #include <linux/list.h>
 #include <linux/security.h>
@@ -70,7 +71,6 @@ struct msg_sender {
 #define msg_ids(ns)    ((ns)->ids[IPC_MSG_IDS])
 
 #define msg_unlock(msq)                ipc_unlock(&(msq)->q_perm)
-#define msg_buildid(id, seq)   ipc_buildid(id, seq)
 
 static void freeque(struct ipc_namespace *, struct kern_ipc_perm *);
 static int newque(struct ipc_namespace *, struct ipc_params *);
@@ -78,11 +78,49 @@ static int newque(struct ipc_namespace *, struct ipc_params *);
 static int sysvipc_msg_proc_show(struct seq_file *s, void *it);
 #endif
 
+/*
+ * Scale msgmni with the available lowmem size: the memory dedicated to msg
+ * queues should occupy at most 1/MSG_MEM_SCALE of lowmem.
+ * Also take into account the number of nsproxies created so far.
+ * This should be done staying within the (MSGMNI , IPCMNI/nr_ipc_ns) range.
+ */
+void recompute_msgmni(struct ipc_namespace *ns)
+{
+       struct sysinfo i;
+       unsigned long allowed;
+       int nb_ns;
+
+       si_meminfo(&i);
+       allowed = (((i.totalram - i.totalhigh) / MSG_MEM_SCALE) * i.mem_unit)
+               / MSGMNB;
+       nb_ns = atomic_read(&nr_ipc_ns);
+       allowed /= nb_ns;
+
+       if (allowed < MSGMNI) {
+               ns->msg_ctlmni = MSGMNI;
+               goto out_callback;
+       }
+
+       if (allowed > IPCMNI / nb_ns) {
+               ns->msg_ctlmni = IPCMNI / nb_ns;
+               goto out_callback;
+       }
+
+       ns->msg_ctlmni = allowed;
+
+out_callback:
+
+       printk(KERN_INFO "msgmni has been set to %d for ipc namespace %p\n",
+               ns->msg_ctlmni, ns);
+}
+
 void msg_init_ns(struct ipc_namespace *ns)
 {
        ns->msg_ctlmax = MSGMAX;
        ns->msg_ctlmnb = MSGMNB;
-       ns->msg_ctlmni = MSGMNI;
+
+       recompute_msgmni(ns);
+
        atomic_set(&ns->msg_bytes, 0);
        atomic_set(&ns->msg_hdrs, 0);
        ipc_init_ids(&ns->ids[IPC_MSG_IDS]);
@@ -103,21 +141,6 @@ void __init msg_init(void)
                                IPC_MSG_IDS, sysvipc_msg_proc_show);
 }
 
-/*
- * This routine is called in the paths where the rw_mutex is held to protect
- * access to the idr tree.
- */
-static inline struct msg_queue *msg_lock_check_down(struct ipc_namespace *ns,
-                                               int id)
-{
-       struct kern_ipc_perm *ipcp = ipc_lock_check_down(&msg_ids(ns), id);
-
-       if (IS_ERR(ipcp))
-               return (struct msg_queue *)ipcp;
-
-       return container_of(ipcp, struct msg_queue, q_perm);
-}
-
 /*
  * msg_lock_(check_) routines are called in the paths where the rw_mutex
  * is not held.
@@ -186,7 +209,6 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
                return id;
        }
 
-       msq->q_perm.id = msg_buildid(id, msq->q_perm.seq);
        msq->q_stime = msq->q_rtime = 0;
        msq->q_ctime = get_seconds();
        msq->q_cbytes = msq->q_qnum = 0;
@@ -324,19 +346,19 @@ copy_msqid_to_user(void __user *buf, struct msqid64_ds *in, int version)
                out.msg_rtime           = in->msg_rtime;
                out.msg_ctime           = in->msg_ctime;
 
-               if (in->msg_cbytes > USHRT_MAX)
-                       out.msg_cbytes  = USHRT_MAX;
+               if (in->msg_cbytes > USHORT_MAX)
+                       out.msg_cbytes  = USHORT_MAX;
                else
                        out.msg_cbytes  = in->msg_cbytes;
                out.msg_lcbytes         = in->msg_cbytes;
 
-               if (in->msg_qnum > USHRT_MAX)
-                       out.msg_qnum    = USHRT_MAX;
+               if (in->msg_qnum > USHORT_MAX)
+                       out.msg_qnum    = USHORT_MAX;
                else
                        out.msg_qnum    = in->msg_qnum;
 
-               if (in->msg_qbytes > USHRT_MAX)
-                       out.msg_qbytes  = USHRT_MAX;
+               if (in->msg_qbytes > USHORT_MAX)
+                       out.msg_qbytes  = USHORT_MAX;
                else
                        out.msg_qbytes  = in->msg_qbytes;
                out.msg_lqbytes         = in->msg_qbytes;
@@ -351,31 +373,14 @@ copy_msqid_to_user(void __user *buf, struct msqid64_ds *in, int version)
        }
 }
 
-struct msq_setbuf {
-       unsigned long   qbytes;
-       uid_t           uid;
-       gid_t           gid;
-       mode_t          mode;
-};
-
 static inline unsigned long
-copy_msqid_from_user(struct msq_setbuf *out, void __user *buf, int version)
+copy_msqid_from_user(struct msqid64_ds *out, void __user *buf, int version)
 {
        switch(version) {
        case IPC_64:
-       {
-               struct msqid64_ds tbuf;
-
-               if (copy_from_user(&tbuf, buf, sizeof(tbuf)))
+               if (copy_from_user(out, buf, sizeof(*out)))
                        return -EFAULT;
-
-               out->qbytes             = tbuf.msg_qbytes;
-               out->uid                = tbuf.msg_perm.uid;
-               out->gid                = tbuf.msg_perm.gid;
-               out->mode               = tbuf.msg_perm.mode;
-
                return 0;
-       }
        case IPC_OLD:
        {
                struct msqid_ds tbuf_old;
@@ -383,14 +388,14 @@ copy_msqid_from_user(struct msq_setbuf *out, void __user *buf, int version)
                if (copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
                        return -EFAULT;
 
-               out->uid                = tbuf_old.msg_perm.uid;
-               out->gid                = tbuf_old.msg_perm.gid;
-               out->mode               = tbuf_old.msg_perm.mode;
+               out->msg_perm.uid       = tbuf_old.msg_perm.uid;
+               out->msg_perm.gid       = tbuf_old.msg_perm.gid;
+               out->msg_perm.mode      = tbuf_old.msg_perm.mode;
 
                if (tbuf_old.msg_qbytes == 0)
-                       out->qbytes     = tbuf_old.msg_lqbytes;
+                       out->msg_qbytes = tbuf_old.msg_lqbytes;
                else
-                       out->qbytes     = tbuf_old.msg_qbytes;
+                       out->msg_qbytes = tbuf_old.msg_qbytes;
 
                return 0;
        }
@@ -399,10 +404,71 @@ copy_msqid_from_user(struct msq_setbuf *out, void __user *buf, int version)
        }
 }
 
-asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
+/*
+ * This function handles some msgctl commands which require the rw_mutex
+ * to be held in write mode.
+ * NOTE: no locks must be held, the rw_mutex is taken inside this function.
+ */
+static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
+                      struct msqid_ds __user *buf, int version)
 {
        struct kern_ipc_perm *ipcp;
-       struct msq_setbuf uninitialized_var(setbuf);
+       struct msqid64_ds msqid64;
+       struct msg_queue *msq;
+       int err;
+
+       if (cmd == IPC_SET) {
+               if (copy_msqid_from_user(&msqid64, buf, version))
+                       return -EFAULT;
+       }
+
+       ipcp = ipcctl_pre_down(&msg_ids(ns), msqid, cmd,
+                              &msqid64.msg_perm, msqid64.msg_qbytes);
+       if (IS_ERR(ipcp))
+               return PTR_ERR(ipcp);
+
+       msq = container_of(ipcp, struct msg_queue, q_perm);
+
+       err = security_msg_queue_msgctl(msq, cmd);
+       if (err)
+               goto out_unlock;
+
+       switch (cmd) {
+       case IPC_RMID:
+               freeque(ns, ipcp);
+               goto out_up;
+       case IPC_SET:
+               if (msqid64.msg_qbytes > ns->msg_ctlmnb &&
+                   !capable(CAP_SYS_RESOURCE)) {
+                       err = -EPERM;
+                       goto out_unlock;
+               }
+
+               msq->q_qbytes = msqid64.msg_qbytes;
+
+               ipc_update_perm(&msqid64.msg_perm, ipcp);
+               msq->q_ctime = get_seconds();
+               /* sleeping receivers might be excluded by
+                * stricter permissions.
+                */
+               expunge_all(msq, -EAGAIN);
+               /* sleeping senders might be able to send
+                * due to a larger queue size.
+                */
+               ss_wakeup(&msq->q_senders, 0);
+               break;
+       default:
+               err = -EINVAL;
+       }
+out_unlock:
+       msg_unlock(msq);
+out_up:
+       up_write(&msg_ids(ns).rw_mutex);
+       return err;
+}
+
+asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
+{
        struct msg_queue *msq;
        int err, version;
        struct ipc_namespace *ns;
@@ -498,82 +564,13 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
                return success_return;
        }
        case IPC_SET:
-               if (!buf)
-                       return -EFAULT;
-               if (copy_msqid_from_user(&setbuf, buf, version))
-                       return -EFAULT;
-               break;
        case IPC_RMID:
-               break;
+               err = msgctl_down(ns, msqid, cmd, buf, version);
+               return err;
        default:
                return  -EINVAL;
        }
 
-       down_write(&msg_ids(ns).rw_mutex);
-       msq = msg_lock_check_down(ns, msqid);
-       if (IS_ERR(msq)) {
-               err = PTR_ERR(msq);
-               goto out_up;
-       }
-
-       ipcp = &msq->q_perm;
-
-       err = audit_ipc_obj(ipcp);
-       if (err)
-               goto out_unlock_up;
-       if (cmd == IPC_SET) {
-               err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid,
-                                        setbuf.mode);
-               if (err)
-                       goto out_unlock_up;
-       }
-
-       err = -EPERM;
-       if (current->euid != ipcp->cuid &&
-           current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
-               /* We _could_ check for CAP_CHOWN above, but we don't */
-               goto out_unlock_up;
-
-       err = security_msg_queue_msgctl(msq, cmd);
-       if (err)
-               goto out_unlock_up;
-
-       switch (cmd) {
-       case IPC_SET:
-       {
-               err = -EPERM;
-               if (setbuf.qbytes > ns->msg_ctlmnb && !capable(CAP_SYS_RESOURCE))
-                       goto out_unlock_up;
-
-               msq->q_qbytes = setbuf.qbytes;
-
-               ipcp->uid = setbuf.uid;
-               ipcp->gid = setbuf.gid;
-               ipcp->mode = (ipcp->mode & ~S_IRWXUGO) |
-                            (S_IRWXUGO & setbuf.mode);
-               msq->q_ctime = get_seconds();
-               /* sleeping receivers might be excluded by
-                * stricter permissions.
-                */
-               expunge_all(msq, -EAGAIN);
-               /* sleeping senders might be able to send
-                * due to a larger queue size.
-                */
-               ss_wakeup(&msq->q_senders, 0);
-               msg_unlock(msq);
-               break;
-       }
-       case IPC_RMID:
-               freeque(ns, &msq->q_perm);
-               break;
-       }
-       err = 0;
-out_up:
-       up_write(&msg_ids(ns).rw_mutex);
-       return err;
-out_unlock_up:
-       msg_unlock(msq);
-       goto out_up;
 out_unlock:
        msg_unlock(msq);
        return err;
index 1b967655eb350eba0c4308998e376a8d3a719c72..9171d948751e72c6c0c8fa1b8e60688ba4384a0c 100644 (file)
@@ -20,10 +20,20 @@ static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns)
        if (ns == NULL)
                return ERR_PTR(-ENOMEM);
 
+       atomic_inc(&nr_ipc_ns);
+
        sem_init_ns(ns);
        msg_init_ns(ns);
        shm_init_ns(ns);
 
+       /*
+        * msgmni has already been computed for the new ipc ns.
+        * Thus, do the ipcns creation notification before registering that
+        * new ipcns in the chain.
+        */
+       ipcns_notify(IPCNS_CREATED);
+       register_ipcns_notifier(ns);
+
        kref_init(&ns->kref);
        return ns;
 }
@@ -79,8 +89,24 @@ void free_ipc_ns(struct kref *kref)
        struct ipc_namespace *ns;
 
        ns = container_of(kref, struct ipc_namespace, kref);
+       /*
+        * Unregistering the hotplug notifier at the beginning guarantees
+        * that the ipc namespace won't be freed while we are inside the
+        * callback routine. Since the blocking_notifier_chain_XXX routines
+        * hold a rw lock on the notifier list, unregister_ipcns_notifier()
+        * won't take the rw lock before blocking_notifier_call_chain() has
+        * released the rd lock.
+        */
+       unregister_ipcns_notifier(ns);
        sem_exit_ns(ns);
        msg_exit_ns(ns);
        shm_exit_ns(ns);
        kfree(ns);
+       atomic_dec(&nr_ipc_ns);
+
+       /*
+        * Do the ipcns removal notification after decrementing nr_ipc_ns in
+        * order to have a correct value when recomputing msgmni.
+        */
+       ipcns_notify(IPCNS_REMOVED);
 }
index 0b45a4d383c6ae662845f5e26c6bc19f25c10a22..e9418df5ff3ecf0c3cb3bb6e6fbac9de5fcac828 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -91,7 +91,6 @@
 
 #define sem_unlock(sma)                ipc_unlock(&(sma)->sem_perm)
 #define sem_checkid(sma, semid)        ipc_checkid(&sma->sem_perm, semid)
-#define sem_buildid(id, seq)   ipc_buildid(id, seq)
 
 static int newary(struct ipc_namespace *, struct ipc_params *);
 static void freeary(struct ipc_namespace *, struct kern_ipc_perm *);
@@ -141,21 +140,6 @@ void __init sem_init (void)
                                IPC_SEM_IDS, sysvipc_sem_proc_show);
 }
 
-/*
- * This routine is called in the paths where the rw_mutex is held to protect
- * access to the idr tree.
- */
-static inline struct sem_array *sem_lock_check_down(struct ipc_namespace *ns,
-                                               int id)
-{
-       struct kern_ipc_perm *ipcp = ipc_lock_check_down(&sem_ids(ns), id);
-
-       if (IS_ERR(ipcp))
-               return (struct sem_array *)ipcp;
-
-       return container_of(ipcp, struct sem_array, sem_perm);
-}
-
 /*
  * sem_lock_(check_) routines are called in the paths where the rw_mutex
  * is not held.
@@ -181,6 +165,25 @@ static inline struct sem_array *sem_lock_check(struct ipc_namespace *ns,
        return container_of(ipcp, struct sem_array, sem_perm);
 }
 
+static inline void sem_lock_and_putref(struct sem_array *sma)
+{
+       ipc_lock_by_ptr(&sma->sem_perm);
+       ipc_rcu_putref(sma);
+}
+
+static inline void sem_getref_and_unlock(struct sem_array *sma)
+{
+       ipc_rcu_getref(sma);
+       ipc_unlock(&(sma)->sem_perm);
+}
+
+static inline void sem_putref(struct sem_array *sma)
+{
+       ipc_lock_by_ptr(&sma->sem_perm);
+       ipc_rcu_putref(sma);
+       ipc_unlock(&(sma)->sem_perm);
+}
+
 static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
 {
        ipc_rmid(&sem_ids(ns), &s->sem_perm);
@@ -268,7 +271,6 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
        }
        ns->used_sems += nsems;
 
-       sma->sem_perm.id = sem_buildid(id, sma->sem_perm.seq);
        sma->sem_base = (struct sem *) &sma[1];
        /* sma->sem_pending = NULL; */
        sma->sem_pending_last = &sma->sem_pending;
@@ -700,19 +702,15 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                int i;
 
                if(nsems > SEMMSL_FAST) {
-                       ipc_rcu_getref(sma);
-                       sem_unlock(sma);                        
+                       sem_getref_and_unlock(sma);
 
                        sem_io = ipc_alloc(sizeof(ushort)*nsems);
                        if(sem_io == NULL) {
-                               ipc_lock_by_ptr(&sma->sem_perm);
-                               ipc_rcu_putref(sma);
-                               sem_unlock(sma);
+                               sem_putref(sma);
                                return -ENOMEM;
                        }
 
-                       ipc_lock_by_ptr(&sma->sem_perm);
-                       ipc_rcu_putref(sma);
+                       sem_lock_and_putref(sma);
                        if (sma->sem_perm.deleted) {
                                sem_unlock(sma);
                                err = -EIDRM;
@@ -733,38 +731,30 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
                int i;
                struct sem_undo *un;
 
-               ipc_rcu_getref(sma);
-               sem_unlock(sma);
+               sem_getref_and_unlock(sma);
 
                if(nsems > SEMMSL_FAST) {
                        sem_io = ipc_alloc(sizeof(ushort)*nsems);
                        if(sem_io == NULL) {
-                               ipc_lock_by_ptr(&sma->sem_perm);
-                               ipc_rcu_putref(sma);
-                               sem_unlock(sma);
+                               sem_putref(sma);
                                return -ENOMEM;
                        }
                }
 
                if (copy_from_user (sem_io, arg.array, nsems*sizeof(ushort))) {
-                       ipc_lock_by_ptr(&sma->sem_perm);
-                       ipc_rcu_putref(sma);
-                       sem_unlock(sma);
+                       sem_putref(sma);
                        err = -EFAULT;
                        goto out_free;
                }
 
                for (i = 0; i < nsems; i++) {
                        if (sem_io[i] > SEMVMX) {
-                               ipc_lock_by_ptr(&sma->sem_perm);
-                               ipc_rcu_putref(sma);
-                               sem_unlock(sma);
+                               sem_putref(sma);
                                err = -ERANGE;
                                goto out_free;
                        }
                }
-               ipc_lock_by_ptr(&sma->sem_perm);
-               ipc_rcu_putref(sma);
+               sem_lock_and_putref(sma);
                if (sma->sem_perm.deleted) {
                        sem_unlock(sma);
                        err = -EIDRM;
@@ -830,28 +820,14 @@ out_free:
        return err;
 }
 
-struct sem_setbuf {
-       uid_t   uid;
-       gid_t   gid;
-       mode_t  mode;
-};
-
-static inline unsigned long copy_semid_from_user(struct sem_setbuf *out, void __user *buf, int version)
+static inline unsigned long
+copy_semid_from_user(struct semid64_ds *out, void __user *buf, int version)
 {
        switch(version) {
        case IPC_64:
-           {
-               struct semid64_ds tbuf;
-
-               if(copy_from_user(&tbuf, buf, sizeof(tbuf)))
+               if (copy_from_user(out, buf, sizeof(*out)))
                        return -EFAULT;
-
-               out->uid        = tbuf.sem_perm.uid;
-               out->gid        = tbuf.sem_perm.gid;
-               out->mode       = tbuf.sem_perm.mode;
-
                return 0;
-           }
        case IPC_OLD:
            {
                struct semid_ds tbuf_old;
@@ -859,9 +835,9 @@ static inline unsigned long copy_semid_from_user(struct sem_setbuf *out, void __
                if(copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
                        return -EFAULT;
 
-               out->uid        = tbuf_old.sem_perm.uid;
-               out->gid        = tbuf_old.sem_perm.gid;
-               out->mode       = tbuf_old.sem_perm.mode;
+               out->sem_perm.uid       = tbuf_old.sem_perm.uid;
+               out->sem_perm.gid       = tbuf_old.sem_perm.gid;
+               out->sem_perm.mode      = tbuf_old.sem_perm.mode;
 
                return 0;
            }
@@ -870,38 +846,29 @@ static inline unsigned long copy_semid_from_user(struct sem_setbuf *out, void __
        }
 }
 
-static int semctl_down(struct ipc_namespace *ns, int semid, int semnum,
-               int cmd, int version, union semun arg)
+/*
+ * This function handles some semctl commands which require the rw_mutex
+ * to be held in write mode.
+ * NOTE: no locks must be held, the rw_mutex is taken inside this function.
+ */
+static int semctl_down(struct ipc_namespace *ns, int semid,
+                      int cmd, int version, union semun arg)
 {
        struct sem_array *sma;
        int err;
-       struct sem_setbuf uninitialized_var(setbuf);
+       struct semid64_ds semid64;
        struct kern_ipc_perm *ipcp;
 
        if(cmd == IPC_SET) {
-               if(copy_semid_from_user (&setbuf, arg.buf, version))
+               if (copy_semid_from_user(&semid64, arg.buf, version))
                        return -EFAULT;
        }
-       sma = sem_lock_check_down(ns, semid);
-       if (IS_ERR(sma))
-               return PTR_ERR(sma);
 
-       ipcp = &sma->sem_perm;
-
-       err = audit_ipc_obj(ipcp);
-       if (err)
-               goto out_unlock;
+       ipcp = ipcctl_pre_down(&sem_ids(ns), semid, cmd, &semid64.sem_perm, 0);
+       if (IS_ERR(ipcp))
+               return PTR_ERR(ipcp);
 
-       if (cmd == IPC_SET) {
-               err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode);
-               if (err)
-                       goto out_unlock;
-       }
-       if (current->euid != ipcp->cuid && 
-           current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) {
-               err=-EPERM;
-               goto out_unlock;
-       }
+       sma = container_of(ipcp, struct sem_array, sem_perm);
 
        err = security_sem_semctl(sma, cmd);
        if (err)
@@ -910,26 +877,19 @@ static int semctl_down(struct ipc_namespace *ns, int semid, int semnum,
        switch(cmd){
        case IPC_RMID:
                freeary(ns, ipcp);
-               err = 0;
-               break;
+               goto out_up;
        case IPC_SET:
-               ipcp->uid = setbuf.uid;
-               ipcp->gid = setbuf.gid;
-               ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
-                               | (setbuf.mode & S_IRWXUGO);
+               ipc_update_perm(&semid64.sem_perm, ipcp);
                sma->sem_ctime = get_seconds();
-               sem_unlock(sma);
-               err = 0;
                break;
        default:
-               sem_unlock(sma);
                err = -EINVAL;
-               break;
        }
-       return err;
 
 out_unlock:
        sem_unlock(sma);
+out_up:
+       up_write(&sem_ids(ns).rw_mutex);
        return err;
 }
 
@@ -963,9 +923,7 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
                return err;
        case IPC_RMID:
        case IPC_SET:
-               down_write(&sem_ids(ns).rw_mutex);
-               err = semctl_down(ns,semid,semnum,cmd,version,arg);
-               up_write(&sem_ids(ns).rw_mutex);
+               err = semctl_down(ns, semid, cmd, version, arg);
                return err;
        default:
                return -EINVAL;
@@ -1044,14 +1002,11 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid)
                return ERR_PTR(PTR_ERR(sma));
 
        nsems = sma->sem_nsems;
-       ipc_rcu_getref(sma);
-       sem_unlock(sma);
+       sem_getref_and_unlock(sma);
 
        new = kzalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL);
        if (!new) {
-               ipc_lock_by_ptr(&sma->sem_perm);
-               ipc_rcu_putref(sma);
-               sem_unlock(sma);
+               sem_putref(sma);
                return ERR_PTR(-ENOMEM);
        }
        new->semadj = (short *) &new[1];
@@ -1062,13 +1017,10 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid)
        if (un) {
                spin_unlock(&ulp->lock);
                kfree(new);
-               ipc_lock_by_ptr(&sma->sem_perm);
-               ipc_rcu_putref(sma);
-               sem_unlock(sma);
+               sem_putref(sma);
                goto out;
        }
-       ipc_lock_by_ptr(&sma->sem_perm);
-       ipc_rcu_putref(sma);
+       sem_lock_and_putref(sma);
        if (sma->sem_perm.deleted) {
                sem_unlock(sma);
                spin_unlock(&ulp->lock);
@@ -1298,6 +1250,7 @@ void exit_sem(struct task_struct *tsk)
        undo_list = tsk->sysvsem.undo_list;
        if (!undo_list)
                return;
+       tsk->sysvsem.undo_list = NULL;
 
        if (!atomic_dec_and_test(&undo_list->refcnt))
                return;
index e636910454a9b80ab9216498b09002c86d93e088..554429ade079ffbcd8b19fbfd657772db2eb36ec 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -60,7 +60,6 @@ static struct vm_operations_struct shm_vm_ops;
 
 #define shm_unlock(shp)                        \
        ipc_unlock(&(shp)->shm_perm)
-#define shm_buildid(id, seq)   ipc_buildid(id, seq)
 
 static int newseg(struct ipc_namespace *, struct ipc_params *);
 static void shm_open(struct vm_area_struct *vma);
@@ -127,18 +126,6 @@ static inline struct shmid_kernel *shm_lock_down(struct ipc_namespace *ns,
        return container_of(ipcp, struct shmid_kernel, shm_perm);
 }
 
-static inline struct shmid_kernel *shm_lock_check_down(
-                                               struct ipc_namespace *ns,
-                                               int id)
-{
-       struct kern_ipc_perm *ipcp = ipc_lock_check_down(&shm_ids(ns), id);
-
-       if (IS_ERR(ipcp))
-               return (struct shmid_kernel *)ipcp;
-
-       return container_of(ipcp, struct shmid_kernel, shm_perm);
-}
-
 /*
  * shm_lock_(check_) routines are called in the paths where the rw_mutex
  * is not held.
@@ -169,12 +156,6 @@ static inline void shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *s)
        ipc_rmid(&shm_ids(ns), &s->shm_perm);
 }
 
-static inline int shm_addid(struct ipc_namespace *ns, struct shmid_kernel *shp)
-{
-       return ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni);
-}
-
-
 
 /* This is called by fork, once for every shm attach. */
 static void shm_open(struct vm_area_struct *vma)
@@ -416,7 +397,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
        if (IS_ERR(file))
                goto no_file;
 
-       id = shm_addid(ns, shp);
+       id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni);
        if (id < 0) {
                error = id;
                goto no_id;
@@ -428,7 +409,6 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
        shp->shm_ctim = get_seconds();
        shp->shm_segsz = size;
        shp->shm_nattch = 0;
-       shp->shm_perm.id = shm_buildid(id, shp->shm_perm.seq);
        shp->shm_file = file;
        /*
         * shmid gets reported as "inode#" in /proc/pid/maps.
@@ -519,28 +499,14 @@ static inline unsigned long copy_shmid_to_user(void __user *buf, struct shmid64_
        }
 }
 
-struct shm_setbuf {
-       uid_t   uid;
-       gid_t   gid;
-       mode_t  mode;
-};     
-
-static inline unsigned long copy_shmid_from_user(struct shm_setbuf *out, void __user *buf, int version)
+static inline unsigned long
+copy_shmid_from_user(struct shmid64_ds *out, void __user *buf, int version)
 {
        switch(version) {
        case IPC_64:
-           {
-               struct shmid64_ds tbuf;
-
-               if (copy_from_user(&tbuf, buf, sizeof(tbuf)))
+               if (copy_from_user(out, buf, sizeof(*out)))
                        return -EFAULT;
-
-               out->uid        = tbuf.shm_perm.uid;
-               out->gid        = tbuf.shm_perm.gid;
-               out->mode       = tbuf.shm_perm.mode;
-
                return 0;
-           }
        case IPC_OLD:
            {
                struct shmid_ds tbuf_old;
@@ -548,9 +514,9 @@ static inline unsigned long copy_shmid_from_user(struct shm_setbuf *out, void __
                if (copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
                        return -EFAULT;
 
-               out->uid        = tbuf_old.shm_perm.uid;
-               out->gid        = tbuf_old.shm_perm.gid;
-               out->mode       = tbuf_old.shm_perm.mode;
+               out->shm_perm.uid       = tbuf_old.shm_perm.uid;
+               out->shm_perm.gid       = tbuf_old.shm_perm.gid;
+               out->shm_perm.mode      = tbuf_old.shm_perm.mode;
 
                return 0;
            }
@@ -624,9 +590,53 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
        }
 }
 
-asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
+/*
+ * This function handles some shmctl commands which require the rw_mutex
+ * to be held in write mode.
+ * NOTE: no locks must be held, the rw_mutex is taken inside this function.
+ */
+static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
+                      struct shmid_ds __user *buf, int version)
+{
+       struct kern_ipc_perm *ipcp;
+       struct shmid64_ds shmid64;
+       struct shmid_kernel *shp;
+       int err;
+
+       if (cmd == IPC_SET) {
+               if (copy_shmid_from_user(&shmid64, buf, version))
+                       return -EFAULT;
+       }
+
+       ipcp = ipcctl_pre_down(&shm_ids(ns), shmid, cmd, &shmid64.shm_perm, 0);
+       if (IS_ERR(ipcp))
+               return PTR_ERR(ipcp);
+
+       shp = container_of(ipcp, struct shmid_kernel, shm_perm);
+
+       err = security_shm_shmctl(shp, cmd);
+       if (err)
+               goto out_unlock;
+       switch (cmd) {
+       case IPC_RMID:
+               do_shm_rmid(ns, ipcp);
+               goto out_up;
+       case IPC_SET:
+               ipc_update_perm(&shmid64.shm_perm, ipcp);
+               shp->shm_ctim = get_seconds();
+               break;
+       default:
+               err = -EINVAL;
+       }
+out_unlock:
+       shm_unlock(shp);
+out_up:
+       up_write(&shm_ids(ns).rw_mutex);
+       return err;
+}
+
+asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
 {
-       struct shm_setbuf setbuf;
        struct shmid_kernel *shp;
        int err, version;
        struct ipc_namespace *ns;
@@ -783,97 +793,13 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
                goto out;
        }
        case IPC_RMID:
-       {
-               /*
-                *      We cannot simply remove the file. The SVID states
-                *      that the block remains until the last person
-                *      detaches from it, then is deleted. A shmat() on
-                *      an RMID segment is legal in older Linux and if 
-                *      we change it apps break...
-                *
-                *      Instead we set a destroyed flag, and then blow
-                *      the name away when the usage hits zero.
-                */
-               down_write(&shm_ids(ns).rw_mutex);
-               shp = shm_lock_check_down(ns, shmid);
-               if (IS_ERR(shp)) {
-                       err = PTR_ERR(shp);
-                       goto out_up;
-               }
-
-               err = audit_ipc_obj(&(shp->shm_perm));
-               if (err)
-                       goto out_unlock_up;
-
-               if (current->euid != shp->shm_perm.uid &&
-                   current->euid != shp->shm_perm.cuid && 
-                   !capable(CAP_SYS_ADMIN)) {
-                       err=-EPERM;
-                       goto out_unlock_up;
-               }
-
-               err = security_shm_shmctl(shp, cmd);
-               if (err)
-                       goto out_unlock_up;
-
-               do_shm_rmid(ns, &shp->shm_perm);
-               up_write(&shm_ids(ns).rw_mutex);
-               goto out;
-       }
-
        case IPC_SET:
-       {
-               if (!buf) {
-                       err = -EFAULT;
-                       goto out;
-               }
-
-               if (copy_shmid_from_user (&setbuf, buf, version)) {
-                       err = -EFAULT;
-                       goto out;
-               }
-               down_write(&shm_ids(ns).rw_mutex);
-               shp = shm_lock_check_down(ns, shmid);
-               if (IS_ERR(shp)) {
-                       err = PTR_ERR(shp);
-                       goto out_up;
-               }
-               err = audit_ipc_obj(&(shp->shm_perm));
-               if (err)
-                       goto out_unlock_up;
-               err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode);
-               if (err)
-                       goto out_unlock_up;
-               err=-EPERM;
-               if (current->euid != shp->shm_perm.uid &&
-                   current->euid != shp->shm_perm.cuid && 
-                   !capable(CAP_SYS_ADMIN)) {
-                       goto out_unlock_up;
-               }
-
-               err = security_shm_shmctl(shp, cmd);
-               if (err)
-                       goto out_unlock_up;
-               
-               shp->shm_perm.uid = setbuf.uid;
-               shp->shm_perm.gid = setbuf.gid;
-               shp->shm_perm.mode = (shp->shm_perm.mode & ~S_IRWXUGO)
-                       | (setbuf.mode & S_IRWXUGO);
-               shp->shm_ctim = get_seconds();
-               break;
-       }
-
+               err = shmctl_down(ns, shmid, cmd, buf, version);
+               return err;
        default:
-               err = -EINVAL;
-               goto out;
+               return -EINVAL;
        }
 
-       err = 0;
-out_unlock_up:
-       shm_unlock(shp);
-out_up:
-       up_write(&shm_ids(ns).rw_mutex);
-       goto out;
 out_unlock:
        shm_unlock(shp);
 out:
index fd1b50da9db8858793a11c0e6c503fb523280786..3339177b336cae51c0b5a8085ad9a087891bb0b2 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/audit.h>
 #include <linux/nsproxy.h>
 #include <linux/rwsem.h>
+#include <linux/memory.h>
 #include <linux/ipc_namespace.h>
 
 #include <asm/unistd.h>
@@ -52,11 +53,57 @@ struct ipc_namespace init_ipc_ns = {
        },
 };
 
+atomic_t nr_ipc_ns = ATOMIC_INIT(1);
+
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+
+static void ipc_memory_notifier(struct work_struct *work)
+{
+       ipcns_notify(IPCNS_MEMCHANGED);
+}
+
+static DECLARE_WORK(ipc_memory_wq, ipc_memory_notifier);
+
+
+static int ipc_memory_callback(struct notifier_block *self,
+                               unsigned long action, void *arg)
+{
+       switch (action) {
+       case MEM_ONLINE:    /* memory successfully brought online */
+       case MEM_OFFLINE:   /* or offline: it's time to recompute msgmni */
+               /*
+                * This is done by invoking the ipcns notifier chain with the
+                * IPC_MEMCHANGED event.
+                * In order not to keep the lock on the hotplug memory chain
+                * for too long, queue a work item that will, when waken up,
+                * activate the ipcns notification chain.
+                * No need to keep several ipc work items on the queue.
+                */
+               if (!work_pending(&ipc_memory_wq))
+                       schedule_work(&ipc_memory_wq);
+               break;
+       case MEM_GOING_ONLINE:
+       case MEM_GOING_OFFLINE:
+       case MEM_CANCEL_ONLINE:
+       case MEM_CANCEL_OFFLINE:
+       default:
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+#endif /* CONFIG_MEMORY_HOTPLUG */
+
 /**
  *     ipc_init        -       initialise IPC subsystem
  *
  *     The various system5 IPC resources (semaphores, messages and shared
  *     memory) are initialised
+ *     A callback routine is registered into the memory hotplug notifier
+ *     chain: since msgmni scales to lowmem this callback routine will be
+ *     called upon successful memory add / remove to recompute msmgni.
  */
  
 static int __init ipc_init(void)
@@ -64,6 +111,8 @@ static int __init ipc_init(void)
        sem_init();
        msg_init();
        shm_init();
+       hotplug_memory_notifier(ipc_memory_callback, IPC_CALLBACK_PRI);
+       register_ipcns_notifier(&init_ipc_ns);
        return 0;
 }
 __initcall(ipc_init);
@@ -84,8 +133,8 @@ void ipc_init_ids(struct ipc_ids *ids)
        ids->seq = 0;
        {
                int seq_limit = INT_MAX/SEQ_MULTIPLIER;
-               if(seq_limit > USHRT_MAX)
-                       ids->seq_max = USHRT_MAX;
+               if (seq_limit > USHORT_MAX)
+                       ids->seq_max = USHORT_MAX;
                 else
                        ids->seq_max = seq_limit;
        }
@@ -116,13 +165,12 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
        iface->ids      = ids;
        iface->show     = show;
 
-       pde = create_proc_entry(path,
-                               S_IRUGO,        /* world readable */
-                               NULL            /* parent dir */);
-       if (pde) {
-               pde->data = iface;
-               pde->proc_fops = &sysvipc_proc_fops;
-       } else {
+       pde = proc_create_data(path,
+                              S_IRUGO,        /* world readable */
+                              NULL,           /* parent dir */
+                              &sysvipc_proc_fops,
+                              iface);
+       if (!pde) {
                kfree(iface);
        }
 }
@@ -231,6 +279,7 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
        if(ids->seq > ids->seq_max)
                ids->seq = 0;
 
+       new->id = ipc_buildid(id, new->seq);
        spin_lock_init(&new->lock);
        new->deleted = 0;
        rcu_read_lock();
@@ -761,6 +810,70 @@ int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
                return ipcget_public(ns, ids, ops, params);
 }
 
+/**
+ * ipc_update_perm - update the permissions of an IPC.
+ * @in:  the permission given as input.
+ * @out: the permission of the ipc to set.
+ */
+void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)
+{
+       out->uid = in->uid;
+       out->gid = in->gid;
+       out->mode = (out->mode & ~S_IRWXUGO)
+               | (in->mode & S_IRWXUGO);
+}
+
+/**
+ * ipcctl_pre_down - retrieve an ipc and check permissions for some IPC_XXX cmd
+ * @ids:  the table of ids where to look for the ipc
+ * @id:   the id of the ipc to retrieve
+ * @cmd:  the cmd to check
+ * @perm: the permission to set
+ * @extra_perm: one extra permission parameter used by msq
+ *
+ * This function does some common audit and permissions check for some IPC_XXX
+ * cmd and is called from semctl_down, shmctl_down and msgctl_down.
+ * It must be called without any lock held and
+ *  - retrieves the ipc with the given id in the given table.
+ *  - performs some audit and permission check, depending on the given cmd
+ *  - returns the ipc with both ipc and rw_mutex locks held in case of success
+ *    or an err-code without any lock held otherwise.
+ */
+struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd,
+                                     struct ipc64_perm *perm, int extra_perm)
+{
+       struct kern_ipc_perm *ipcp;
+       int err;
+
+       down_write(&ids->rw_mutex);
+       ipcp = ipc_lock_check_down(ids, id);
+       if (IS_ERR(ipcp)) {
+               err = PTR_ERR(ipcp);
+               goto out_up;
+       }
+
+       err = audit_ipc_obj(ipcp);
+       if (err)
+               goto out_unlock;
+
+       if (cmd == IPC_SET) {
+               err = audit_ipc_set_perm(extra_perm, perm->uid,
+                                        perm->gid, perm->mode);
+               if (err)
+                       goto out_unlock;
+       }
+       if (current->euid == ipcp->cuid ||
+           current->euid == ipcp->uid || capable(CAP_SYS_ADMIN))
+               return ipcp;
+
+       err = -EPERM;
+out_unlock:
+       ipc_unlock(ipcp);
+out_up:
+       up_write(&ids->rw_mutex);
+       return ERR_PTR(err);
+}
+
 #ifdef __ARCH_WANT_IPC_PARSE_VERSION
 
 
index f37d160c98fe7c5c42b44d9611979a4a79d793fc..cdb966aebe0716e8375617431d5734ed45aa639f 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <linux/err.h>
 
-#define USHRT_MAX 0xffff
 #define SEQ_MULTIPLIER (IPCMNI)
 
 void sem_init (void);
@@ -112,6 +111,9 @@ struct kern_ipc_perm *ipc_lock(struct ipc_ids *, int);
 
 void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out);
 void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out);
+void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out);
+struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd,
+                                     struct ipc64_perm *perm, int extra_perm);
 
 #if defined(__ia64__) || defined(__x86_64__) || defined(__hppa__) || defined(__XTENSA__)
   /* On IA-64, we always use the "64-bit version" of the IPC structures.  */ 
@@ -124,6 +126,8 @@ extern void free_msg(struct msg_msg *msg);
 extern struct msg_msg *load_msg(const void __user *src, int len);
 extern int store_msg(void __user *dest, struct msg_msg *msg, int len);
 
+extern void recompute_msgmni(struct ipc_namespace *);
+
 static inline int ipc_buildid(int id, int seq)
 {
        return SEQ_MULTIPLIER * seq + id;
index 6c5f081132a41862f1d8ffe3cee713e44d553685..188c43223f52a33e3b948dba43124a70cd349e30 100644 (file)
@@ -11,7 +11,7 @@ obj-y     = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
            hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \
            notifier.o ksysfs.o pm_qos_params.o
 
-obj-$(CONFIG_SYSCTL) += sysctl_check.o
+obj-$(CONFIG_SYSCTL_SYSCALL_CHECK) += sysctl_check.o
 obj-$(CONFIG_STACKTRACE) += stacktrace.o
 obj-y += time/
 obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o
index a7b16086d36f7b863a19697eed4877b67226b197..b7d3709cc452afdba06492ecf2c977bab04dd530 100644 (file)
@@ -126,6 +126,8 @@ static int     audit_freelist_count;
 static LIST_HEAD(audit_freelist);
 
 static struct sk_buff_head audit_skb_queue;
+/* queue of skbs to send to auditd when/if it comes back */
+static struct sk_buff_head audit_skb_hold_queue;
 static struct task_struct *kauditd_task;
 static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait);
 static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait);
@@ -154,6 +156,11 @@ struct audit_buffer {
        gfp_t                gfp_mask;
 };
 
+struct audit_reply {
+       int pid;
+       struct sk_buff *skb;
+};
+
 static void audit_set_pid(struct audit_buffer *ab, pid_t pid)
 {
        if (ab) {
@@ -252,14 +259,15 @@ void audit_log_lost(const char *message)
 }
 
 static int audit_log_config_change(char *function_name, int new, int old,
-                                  uid_t loginuid, u32 sid, int allow_changes)
+                                  uid_t loginuid, u32 sessionid, u32 sid,
+                                  int allow_changes)
 {
        struct audit_buffer *ab;
        int rc = 0;
 
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
-       audit_log_format(ab, "%s=%d old=%d by auid=%u", function_name, new,
-                        old, loginuid);
+       audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new,
+                        old, loginuid, sessionid);
        if (sid) {
                char *ctx = NULL;
                u32 len;
@@ -279,7 +287,8 @@ static int audit_log_config_change(char *function_name, int new, int old,
 }
 
 static int audit_do_config_change(char *function_name, int *to_change,
-                                 int new, uid_t loginuid, u32 sid)
+                                 int new, uid_t loginuid, u32 sessionid,
+                                 u32 sid)
 {
        int allow_changes, rc = 0, old = *to_change;
 
@@ -290,8 +299,8 @@ static int audit_do_config_change(char *function_name, int *to_change,
                allow_changes = 1;
 
        if (audit_enabled != AUDIT_OFF) {
-               rc = audit_log_config_change(function_name, new, old,
-                                            loginuid, sid, allow_changes);
+               rc = audit_log_config_change(function_name, new, old, loginuid,
+                                            sessionid, sid, allow_changes);
                if (rc)
                        allow_changes = 0;
        }
@@ -305,26 +314,28 @@ static int audit_do_config_change(char *function_name, int *to_change,
        return rc;
 }
 
-static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid)
+static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sessionid,
+                               u32 sid)
 {
        return audit_do_config_change("audit_rate_limit", &audit_rate_limit,
-                                     limit, loginuid, sid);
+                                     limit, loginuid, sessionid, sid);
 }
 
-static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid)
+static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sessionid,
+                                  u32 sid)
 {
        return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit,
-                                     limit, loginuid, sid);
+                                     limit, loginuid, sessionid, sid);
 }
 
-static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
+static int audit_set_enabled(int state, uid_t loginuid, u32 sessionid, u32 sid)
 {
        int rc;
        if (state < AUDIT_OFF || state > AUDIT_LOCKED)
                return -EINVAL;
 
        rc =  audit_do_config_change("audit_enabled", &audit_enabled, state,
-                                    loginuid, sid);
+                                    loginuid, sessionid, sid);
 
        if (!rc)
                audit_ever_enabled |= !!state;
@@ -332,7 +343,7 @@ static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
        return rc;
 }
 
-static int audit_set_failure(int state, uid_t loginuid, u32 sid)
+static int audit_set_failure(int state, uid_t loginuid, u32 sessionid, u32 sid)
 {
        if (state != AUDIT_FAIL_SILENT
            && state != AUDIT_FAIL_PRINTK
@@ -340,7 +351,43 @@ static int audit_set_failure(int state, uid_t loginuid, u32 sid)
                return -EINVAL;
 
        return audit_do_config_change("audit_failure", &audit_failure, state,
-                                     loginuid, sid);
+                                     loginuid, sessionid, sid);
+}
+
+/*
+ * Queue skbs to be sent to auditd when/if it comes back.  These skbs should
+ * already have been sent via prink/syslog and so if these messages are dropped
+ * it is not a huge concern since we already passed the audit_log_lost()
+ * notification and stuff.  This is just nice to get audit messages during
+ * boot before auditd is running or messages generated while auditd is stopped.
+ * This only holds messages is audit_default is set, aka booting with audit=1
+ * or building your kernel that way.
+ */
+static void audit_hold_skb(struct sk_buff *skb)
+{
+       if (audit_default &&
+           skb_queue_len(&audit_skb_hold_queue) < audit_backlog_limit)
+               skb_queue_tail(&audit_skb_hold_queue, skb);
+       else
+               kfree_skb(skb);
+}
+
+static void kauditd_send_skb(struct sk_buff *skb)
+{
+       int err;
+       /* take a reference in case we can't send it and we want to hold it */
+       skb_get(skb);
+       err = netlink_unicast(audit_sock, skb, audit_nlk_pid, 0);
+       if (err < 0) {
+               BUG_ON(err != -ECONNREFUSED); /* Shoudn't happen */
+               printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid);
+               audit_log_lost("auditd dissapeared\n");
+               audit_pid = 0;
+               /* we might get lucky and get this in the next auditd */
+               audit_hold_skb(skb);
+       } else
+               /* drop the extra reference if sent ok */
+               kfree_skb(skb);
 }
 
 static int kauditd_thread(void *dummy)
@@ -349,24 +396,41 @@ static int kauditd_thread(void *dummy)
 
        set_freezable();
        while (!kthread_should_stop()) {
+               /*
+                * if auditd just started drain the queue of messages already
+                * sent to syslog/printk.  remember loss here is ok.  we already
+                * called audit_log_lost() if it didn't go out normally.  so the
+                * race between the skb_dequeue and the next check for audit_pid
+                * doesn't matter.
+                *
+                * if you ever find kauditd to be too slow we can get a perf win
+                * by doing our own locking and keeping better track if there
+                * are messages in this queue.  I don't see the need now, but
+                * in 5 years when I want to play with this again I'll see this
+                * note and still have no friggin idea what i'm thinking today.
+                */
+               if (audit_default && audit_pid) {
+                       skb = skb_dequeue(&audit_skb_hold_queue);
+                       if (unlikely(skb)) {
+                               while (skb && audit_pid) {
+                                       kauditd_send_skb(skb);
+                                       skb = skb_dequeue(&audit_skb_hold_queue);
+                               }
+                       }
+               }
+
                skb = skb_dequeue(&audit_skb_queue);
                wake_up(&audit_backlog_wait);
                if (skb) {
-                       if (audit_pid) {
-                               int err = netlink_unicast(audit_sock, skb, audit_nlk_pid, 0);
-                               if (err < 0) {
-                                       BUG_ON(err != -ECONNREFUSED); /* Shoudn't happen */
-                                       printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid);
-                                       audit_log_lost("auditd dissapeared\n");
-                                       audit_pid = 0;
-                               }
-                       } else {
+                       if (audit_pid)
+                               kauditd_send_skb(skb);
+                       else {
                                if (printk_ratelimit())
-                                       printk(KERN_NOTICE "%s\n", skb->data +
-                                               NLMSG_SPACE(0));
+                                       printk(KERN_NOTICE "%s\n", skb->data + NLMSG_SPACE(0));
                                else
                                        audit_log_lost("printk limit exceeded\n");
-                               kfree_skb(skb);
+
+                               audit_hold_skb(skb);
                        }
                } else {
                        DECLARE_WAITQUEUE(wait, current);
@@ -385,13 +449,13 @@ static int kauditd_thread(void *dummy)
        return 0;
 }
 
-static int audit_prepare_user_tty(pid_t pid, uid_t loginuid)
+static int audit_prepare_user_tty(pid_t pid, uid_t loginuid, u32 sessionid)
 {
        struct task_struct *tsk;
        int err;
 
        read_lock(&tasklist_lock);
-       tsk = find_task_by_pid(pid);
+       tsk = find_task_by_vpid(pid);
        err = -ESRCH;
        if (!tsk)
                goto out;
@@ -404,7 +468,7 @@ static int audit_prepare_user_tty(pid_t pid, uid_t loginuid)
        if (err)
                goto out;
 
-       tty_audit_push_task(tsk, loginuid);
+       tty_audit_push_task(tsk, loginuid, sessionid);
 out:
        read_unlock(&tasklist_lock);
        return err;
@@ -469,6 +533,19 @@ nlmsg_failure:                     /* Used by NLMSG_PUT */
        return NULL;
 }
 
+static int audit_send_reply_thread(void *arg)
+{
+       struct audit_reply *reply = (struct audit_reply *)arg;
+
+       mutex_lock(&audit_cmd_mutex);
+       mutex_unlock(&audit_cmd_mutex);
+
+       /* Ignore failure. It'll only happen if the sender goes away,
+          because our timeout is set to infinite. */
+       netlink_unicast(audit_sock, reply->skb, reply->pid, 0);
+       kfree(reply);
+       return 0;
+}
 /**
  * audit_send_reply - send an audit reply message via netlink
  * @pid: process id to send reply to
@@ -485,14 +562,26 @@ nlmsg_failure:                    /* Used by NLMSG_PUT */
 void audit_send_reply(int pid, int seq, int type, int done, int multi,
                      void *payload, int size)
 {
-       struct sk_buff  *skb;
+       struct sk_buff *skb;
+       struct task_struct *tsk;
+       struct audit_reply *reply = kmalloc(sizeof(struct audit_reply),
+                                           GFP_KERNEL);
+
+       if (!reply)
+               return;
+
        skb = audit_make_reply(pid, seq, type, done, multi, payload, size);
        if (!skb)
                return;
-       /* Ignore failure. It'll only happen if the sender goes away,
-          because our timeout is set to infinite. */
-       netlink_unicast(audit_sock, skb, pid, 0);
-       return;
+
+       reply->pid = pid;
+       reply->skb = skb;
+
+       tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply");
+       if (IS_ERR(tsk)) {
+               kfree(reply);
+               kfree_skb(skb);
+       }
 }
 
 /*
@@ -534,7 +623,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
 }
 
 static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
-                                    u32 pid, u32 uid, uid_t auid, u32 sid)
+                                    u32 pid, u32 uid, uid_t auid, u32 ses,
+                                    u32 sid)
 {
        int rc = 0;
        char *ctx = NULL;
@@ -546,8 +636,8 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
        }
 
        *ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
-       audit_log_format(*ab, "user pid=%d uid=%u auid=%u",
-                        pid, uid, auid);
+       audit_log_format(*ab, "user pid=%d uid=%u auid=%u ses=%u",
+                        pid, uid, auid, ses);
        if (sid) {
                rc = security_secid_to_secctx(sid, &ctx, &len);
                if (rc)
@@ -570,6 +660,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        struct audit_buffer     *ab;
        u16                     msg_type = nlh->nlmsg_type;
        uid_t                   loginuid; /* loginuid of sender */
+       u32                     sessionid;
        struct audit_sig_info   *sig_data;
        char                    *ctx = NULL;
        u32                     len;
@@ -591,6 +682,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        pid  = NETLINK_CREDS(skb)->pid;
        uid  = NETLINK_CREDS(skb)->uid;
        loginuid = NETLINK_CB(skb).loginuid;
+       sessionid = NETLINK_CB(skb).sessionid;
        sid  = NETLINK_CB(skb).sid;
        seq  = nlh->nlmsg_seq;
        data = NLMSG_DATA(nlh);
@@ -613,12 +705,12 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                status_get   = (struct audit_status *)data;
                if (status_get->mask & AUDIT_STATUS_ENABLED) {
                        err = audit_set_enabled(status_get->enabled,
-                                                       loginuid, sid);
+                                               loginuid, sessionid, sid);
                        if (err < 0) return err;
                }
                if (status_get->mask & AUDIT_STATUS_FAILURE) {
                        err = audit_set_failure(status_get->failure,
-                                                        loginuid, sid);
+                                               loginuid, sessionid, sid);
                        if (err < 0) return err;
                }
                if (status_get->mask & AUDIT_STATUS_PID) {
@@ -627,17 +719,17 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        if (audit_enabled != AUDIT_OFF)
                                audit_log_config_change("audit_pid", new_pid,
                                                        audit_pid, loginuid,
-                                                       sid, 1);
+                                                       sessionid, sid, 1);
 
                        audit_pid = new_pid;
                        audit_nlk_pid = NETLINK_CB(skb).pid;
                }
                if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
                        err = audit_set_rate_limit(status_get->rate_limit,
-                                                        loginuid, sid);
+                                                  loginuid, sessionid, sid);
                if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)
                        err = audit_set_backlog_limit(status_get->backlog_limit,
-                                                       loginuid, sid);
+                                                     loginuid, sessionid, sid);
                break;
        case AUDIT_USER:
        case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG:
@@ -649,12 +741,13 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                if (err == 1) {
                        err = 0;
                        if (msg_type == AUDIT_USER_TTY) {
-                               err = audit_prepare_user_tty(pid, loginuid);
+                               err = audit_prepare_user_tty(pid, loginuid,
+                                                            sessionid);
                                if (err)
                                        break;
                        }
                        audit_log_common_recv_msg(&ab, msg_type, pid, uid,
-                                                 loginuid, sid);
+                                                 loginuid, sessionid, sid);
 
                        if (msg_type != AUDIT_USER_TTY)
                                audit_log_format(ab, " msg='%.1024s'",
@@ -664,8 +757,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 
                                audit_log_format(ab, " msg=");
                                size = nlmsg_len(nlh);
-                               audit_log_n_untrustedstring(ab, size,
-                                                           data);
+                               audit_log_n_untrustedstring(ab, data, size);
                        }
                        audit_set_pid(ab, pid);
                        audit_log_end(ab);
@@ -677,7 +769,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        return -EINVAL;
                if (audit_enabled == AUDIT_LOCKED) {
                        audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid,
-                                                 uid, loginuid, sid);
+                                                 uid, loginuid, sessionid, sid);
 
                        audit_log_format(ab, " audit_enabled=%d res=0",
                                         audit_enabled);
@@ -688,7 +780,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        case AUDIT_LIST:
                err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
                                           uid, seq, data, nlmsg_len(nlh),
-                                          loginuid, sid);
+                                          loginuid, sessionid, sid);
                break;
        case AUDIT_ADD_RULE:
        case AUDIT_DEL_RULE:
@@ -696,7 +788,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        return -EINVAL;
                if (audit_enabled == AUDIT_LOCKED) {
                        audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid,
-                                                 uid, loginuid, sid);
+                                                 uid, loginuid, sessionid, sid);
 
                        audit_log_format(ab, " audit_enabled=%d res=0",
                                         audit_enabled);
@@ -707,13 +799,13 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        case AUDIT_LIST_RULES:
                err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
                                           uid, seq, data, nlmsg_len(nlh),
-                                          loginuid, sid);
+                                          loginuid, sessionid, sid);
                break;
        case AUDIT_TRIM:
                audit_trim_trees();
 
                audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid,
-                                         uid, loginuid, sid);
+                                         uid, loginuid, sessionid, sid);
 
                audit_log_format(ab, " op=trim res=1");
                audit_log_end(ab);
@@ -721,21 +813,21 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        case AUDIT_MAKE_EQUIV: {
                void *bufp = data;
                u32 sizes[2];
-               size_t len = nlmsg_len(nlh);
+               size_t msglen = nlmsg_len(nlh);
                char *old, *new;
 
                err = -EINVAL;
-               if (len < 2 * sizeof(u32))
+               if (msglen < 2 * sizeof(u32))
                        break;
                memcpy(sizes, bufp, 2 * sizeof(u32));
                bufp += 2 * sizeof(u32);
-               len -= 2 * sizeof(u32);
-               old = audit_unpack_string(&bufp, &len, sizes[0]);
+               msglen -= 2 * sizeof(u32);
+               old = audit_unpack_string(&bufp, &msglen, sizes[0]);
                if (IS_ERR(old)) {
                        err = PTR_ERR(old);
                        break;
                }
-               new = audit_unpack_string(&bufp, &len, sizes[1]);
+               new = audit_unpack_string(&bufp, &msglen, sizes[1]);
                if (IS_ERR(new)) {
                        err = PTR_ERR(new);
                        kfree(old);
@@ -745,7 +837,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                err = audit_tag_tree(old, new);
 
                audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid,
-                                         uid, loginuid, sid);
+                                         uid, loginuid, sessionid, sid);
 
                audit_log_format(ab, " op=make_equiv old=");
                audit_log_untrustedstring(ab, old);
@@ -779,7 +871,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                struct task_struct *tsk;
 
                read_lock(&tasklist_lock);
-               tsk = find_task_by_pid(pid);
+               tsk = find_task_by_vpid(pid);
                if (!tsk)
                        err = -ESRCH;
                else {
@@ -802,7 +894,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                if (s->enabled != 0 && s->enabled != 1)
                        return -EINVAL;
                read_lock(&tasklist_lock);
-               tsk = find_task_by_pid(pid);
+               tsk = find_task_by_vpid(pid);
                if (!tsk)
                        err = -ESRCH;
                else {
@@ -877,6 +969,7 @@ static int __init audit_init(void)
                audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
 
        skb_queue_head_init(&audit_skb_queue);
+       skb_queue_head_init(&audit_skb_hold_queue);
        audit_initialized = 1;
        audit_enabled = audit_default;
        audit_ever_enabled |= !!audit_default;
@@ -1199,7 +1292,7 @@ void audit_log_format(struct audit_buffer *ab, const char *fmt, ...)
  * This function will take the passed buf and convert it into a string of
  * ascii hex digits. The new string is placed onto the skb.
  */
-void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf,
+void audit_log_n_hex(struct audit_buffer *ab, const unsigned char *buf,
                size_t len)
 {
        int i, avail, new_len;
@@ -1235,8 +1328,8 @@ void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf,
  * Format a string of no more than slen characters into the audit buffer,
  * enclosed in quote marks.
  */
-static void audit_log_n_string(struct audit_buffer *ab, size_t slen,
-                              const char *string)
+void audit_log_n_string(struct audit_buffer *ab, const char *string,
+                       size_t slen)
 {
        int avail, new_len;
        unsigned char *ptr;
@@ -1292,13 +1385,13 @@ int audit_string_contains_control(const char *string, size_t len)
  * The caller specifies the number of characters in the string to log, which may
  * or may not be the entire string.
  */
-void audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len,
-                                const char *string)
+void audit_log_n_untrustedstring(struct audit_buffer *ab, const char *string,
+                                size_t len)
 {
        if (audit_string_contains_control(string, len))
-               audit_log_hex(ab, string, len);
+               audit_log_n_hex(ab, string, len);
        else
-               audit_log_n_string(ab, len, string);
+               audit_log_n_string(ab, string, len);
 }
 
 /**
@@ -1311,7 +1404,7 @@ void audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len,
  */
 void audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
 {
-       audit_log_n_untrustedstring(ab, strlen(string), string);
+       audit_log_n_untrustedstring(ab, string, strlen(string));
 }
 
 /* This is a helper-function to print the escaped d_path */
@@ -1355,19 +1448,23 @@ void audit_log_end(struct audit_buffer *ab)
                audit_log_lost("rate limit exceeded");
        } else {
                struct nlmsghdr *nlh = nlmsg_hdr(ab->skb);
+               nlh->nlmsg_len = ab->skb->len - NLMSG_SPACE(0);
+
                if (audit_pid) {
-                       nlh->nlmsg_len = ab->skb->len - NLMSG_SPACE(0);
                        skb_queue_tail(&audit_skb_queue, ab->skb);
-                       ab->skb = NULL;
                        wake_up_interruptible(&kauditd_wait);
-               } else if (nlh->nlmsg_type != AUDIT_EOE) {
-                       if (printk_ratelimit()) {
-                               printk(KERN_NOTICE "type=%d %s\n",
-                                       nlh->nlmsg_type,
-                                       ab->skb->data + NLMSG_SPACE(0));
-                       } else
-                               audit_log_lost("printk limit exceeded\n");
+               } else {
+                       if (nlh->nlmsg_type != AUDIT_EOE) {
+                               if (printk_ratelimit()) {
+                                       printk(KERN_NOTICE "type=%d %s\n",
+                                               nlh->nlmsg_type,
+                                               ab->skb->data + NLMSG_SPACE(0));
+                               } else
+                                       audit_log_lost("printk limit exceeded\n");
+                       }
+                       audit_hold_skb(ab->skb);
                }
+               ab->skb = NULL;
        }
        audit_buffer_free(ab);
 }
index 3cfc54ee3e1f054d6533bbe6370d272ba2748c25..9d6717412fecd75eb36029b1c65d84228602b723 100644 (file)
@@ -74,6 +74,11 @@ struct audit_entry {
        struct audit_krule      rule;
 };
 
+#ifdef CONFIG_AUDIT
+extern int audit_enabled;
+extern int audit_ever_enabled;
+#endif
+
 extern int audit_pid;
 
 #define AUDIT_INODE_BUCKETS    32
@@ -104,6 +109,9 @@ struct audit_netlink_list {
 int audit_send_list(void *);
 
 struct inotify_watch;
+/* Inotify handle */
+extern struct inotify_handle *audit_ih;
+
 extern void audit_free_parent(struct inotify_watch *);
 extern void audit_handle_ievent(struct inotify_watch *, u32, u32, u32,
                                const char *, struct inode *);
@@ -111,6 +119,7 @@ extern int selinux_audit_rule_update(void);
 
 extern struct mutex audit_filter_mutex;
 extern void audit_free_rule_rcu(struct rcu_head *);
+extern struct list_head audit_filter_list[];
 
 #ifdef CONFIG_AUDIT_TREE
 extern struct audit_chunk *audit_tree_lookup(const struct inode *);
@@ -137,6 +146,10 @@ extern void audit_put_tree(struct audit_tree *);
 
 extern char *audit_unpack_string(void **, size_t *, size_t);
 
+extern pid_t audit_sig_pid;
+extern uid_t audit_sig_uid;
+extern u32 audit_sig_sid;
+
 #ifdef CONFIG_AUDITSYSCALL
 extern int __audit_signal_info(int sig, struct task_struct *t);
 static inline int audit_signal_info(int sig, struct task_struct *t)
index 28fef6bf85348ea0e363a9ecfc1b362df817656e..0e0bd27e65129ec94e087753ba398c42f92acc7e 100644 (file)
@@ -89,14 +89,9 @@ struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
 
 DEFINE_MUTEX(audit_filter_mutex);
 
-/* Inotify handle */
-extern struct inotify_handle *audit_ih;
-
 /* Inotify events we care about. */
 #define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF
 
-extern int audit_enabled;
-
 void audit_free_parent(struct inotify_watch *i_watch)
 {
        struct audit_parent *parent;
@@ -272,7 +267,7 @@ static int audit_to_watch(struct audit_krule *krule, char *path, int len,
                return -EINVAL;
 
        watch = audit_init_watch(path);
-       if (unlikely(IS_ERR(watch)))
+       if (IS_ERR(watch))
                return PTR_ERR(watch);
 
        audit_get_watch(watch);
@@ -422,7 +417,7 @@ exit_err:
 static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
 {
        struct audit_entry *entry;
-       struct audit_field *f;
+       struct audit_field *ino_f;
        int err = 0;
        int i;
 
@@ -483,6 +478,10 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
                        if (f->val & ~15)
                                goto exit_free;
                        break;
+               case AUDIT_FILETYPE:
+                       if ((f->val & ~S_IFMT) > S_IFMT)
+                               goto exit_free;
+                       break;
                case AUDIT_INODE:
                        err = audit_to_inode(&entry->rule, f);
                        if (err)
@@ -504,9 +503,9 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
                }
        }
 
-       f = entry->rule.inode_f;
-       if (f) {
-               switch(f->op) {
+       ino_f = entry->rule.inode_f;
+       if (ino_f) {
+               switch(ino_f->op) {
                case AUDIT_NOT_EQUAL:
                        entry->rule.inode_f = NULL;
                case AUDIT_EQUAL:
@@ -531,7 +530,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
 {
        int err = 0;
        struct audit_entry *entry;
-       struct audit_field *f;
+       struct audit_field *ino_f;
        void *bufp;
        size_t remain = datasz - sizeof(struct audit_rule_data);
        int i;
@@ -654,14 +653,18 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
                        if (f->val & ~15)
                                goto exit_free;
                        break;
+               case AUDIT_FILETYPE:
+                       if ((f->val & ~S_IFMT) > S_IFMT)
+                               goto exit_free;
+                       break;
                default:
                        goto exit_free;
                }
        }
 
-       f = entry->rule.inode_f;
-       if (f) {
-               switch(f->op) {
+       ino_f = entry->rule.inode_f;
+       if (ino_f) {
+               switch(ino_f->op) {
                case AUDIT_NOT_EQUAL:
                        entry->rule.inode_f = NULL;
                case AUDIT_EQUAL:
@@ -848,7 +851,7 @@ static struct audit_watch *audit_dupe_watch(struct audit_watch *old)
                return ERR_PTR(-ENOMEM);
 
        new = audit_init_watch(path);
-       if (unlikely(IS_ERR(new))) {
+       if (IS_ERR(new)) {
                kfree(path);
                goto out;
        }
@@ -989,7 +992,7 @@ static void audit_update_watch(struct audit_parent *parent,
                        audit_set_auditable(current->audit_context);
 
                nwatch = audit_dupe_watch(owatch);
-               if (unlikely(IS_ERR(nwatch))) {
+               if (IS_ERR(nwatch)) {
                        mutex_unlock(&audit_filter_mutex);
                        audit_panic("error updating watch, skipping");
                        return;
@@ -1004,7 +1007,7 @@ static void audit_update_watch(struct audit_parent *parent,
                        list_del_rcu(&oentry->list);
 
                        nentry = audit_dupe_rule(&oentry->rule, nwatch);
-                       if (unlikely(IS_ERR(nentry)))
+                       if (IS_ERR(nentry))
                                audit_panic("error updating watch, removing");
                        else {
                                int h = audit_hash_ino((u32)ino);
@@ -1500,8 +1503,9 @@ static void audit_list_rules(int pid, int seq, struct sk_buff_head *q)
 }
 
 /* Log rule additions and removals */
-static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
-                                 struct audit_krule *rule, int res)
+static void audit_log_rule_change(uid_t loginuid, u32 sessionid, u32 sid,
+                                 char *action, struct audit_krule *rule,
+                                 int res)
 {
        struct audit_buffer *ab;
 
@@ -1511,7 +1515,7 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
        if (!ab)
                return;
-       audit_log_format(ab, "auid=%u", loginuid);
+       audit_log_format(ab, "auid=%u ses=%u", loginuid, sessionid);
        if (sid) {
                char *ctx = NULL;
                u32 len;
@@ -1543,7 +1547,7 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
  * @sid: SE Linux Security ID of sender
  */
 int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
-                        size_t datasz, uid_t loginuid, u32 sid)
+                        size_t datasz, uid_t loginuid, u32 sessionid, u32 sid)
 {
        struct task_struct *tsk;
        struct audit_netlink_list *dest;
@@ -1590,7 +1594,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
 
                err = audit_add_rule(entry,
                                     &audit_filter_list[entry->rule.listnr]);
-               audit_log_rule_change(loginuid, sid, "add", &entry->rule, !err);
+               audit_log_rule_change(loginuid, sessionid, sid, "add",
+                                     &entry->rule, !err);
 
                if (err)
                        audit_free_rule(entry);
@@ -1606,8 +1611,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
 
                err = audit_del_rule(entry,
                                     &audit_filter_list[entry->rule.listnr]);
-               audit_log_rule_change(loginuid, sid, "remove", &entry->rule,
-                                     !err);
+               audit_log_rule_change(loginuid, sessionid, sid, "remove",
+                                     &entry->rule, !err);
 
                audit_free_rule(entry);
                break;
@@ -1785,7 +1790,7 @@ int audit_update_lsm_rules(void)
                        watch = entry->rule.watch;
                        tree = entry->rule.tree;
                        nentry = audit_dupe_rule(&entry->rule, watch);
-                       if (unlikely(IS_ERR(nentry))) {
+                       if (IS_ERR(nentry)) {
                                /* save the first error encountered for the
                                 * return value */
                                if (!err)
index 56e56ed594a840e9061aac32b7aedfab076d81e9..c10e7aae04d795714fb8cf4ee9326eff4bf6c472 100644 (file)
@@ -68,9 +68,6 @@
 
 #include "audit.h"
 
-extern struct list_head audit_filter_list[];
-extern int audit_ever_enabled;
-
 /* AUDIT_NAMES is the number of slots we reserve in the audit_context
  * for saving names from getname(). */
 #define AUDIT_NAMES    20
@@ -283,6 +280,19 @@ static int audit_match_perm(struct audit_context *ctx, int mask)
        }
 }
 
+static int audit_match_filetype(struct audit_context *ctx, int which)
+{
+       unsigned index = which & ~S_IFMT;
+       mode_t mode = which & S_IFMT;
+       if (index >= ctx->name_count)
+               return 0;
+       if (ctx->names[index].ino == -1)
+               return 0;
+       if ((ctx->names[index].mode ^ mode) & S_IFMT)
+               return 0;
+       return 1;
+}
+
 /*
  * We keep a linked list of fixed-sized (31 pointer) arrays of audit_chunk *;
  * ->first_trees points to its beginning, ->trees - to the current end of data.
@@ -592,6 +602,9 @@ static int audit_filter_rules(struct task_struct *tsk,
                case AUDIT_PERM:
                        result = audit_match_perm(ctx, f->val);
                        break;
+               case AUDIT_FILETYPE:
+                       result = audit_match_filetype(ctx, f->val);
+                       break;
                }
 
                if (!result)
@@ -1095,7 +1108,7 @@ static int audit_log_single_execve_arg(struct audit_context *context,
                        audit_log_format(*ab, "[%d]", i);
                audit_log_format(*ab, "=");
                if (has_cntl)
-                       audit_log_hex(*ab, buf, to_send);
+                       audit_log_n_hex(*ab, buf, to_send);
                else
                        audit_log_format(*ab, "\"%s\"", buf);
                audit_log_format(*ab, "\n");
@@ -1296,7 +1309,6 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                        break; }
 
                case AUDIT_SOCKETCALL: {
-                       int i;
                        struct audit_aux_data_socketcall *axs = (void *)aux;
                        audit_log_format(ab, "nargs=%d", axs->nargs);
                        for (i=0; i<axs->nargs; i++)
@@ -1307,7 +1319,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                        struct audit_aux_data_sockaddr *axs = (void *)aux;
 
                        audit_log_format(ab, "saddr=");
-                       audit_log_hex(ab, axs->a, axs->len);
+                       audit_log_n_hex(ab, axs->a, axs->len);
                        break; }
 
                case AUDIT_FD_PAIR: {
@@ -1321,7 +1333,6 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
 
        for (aux = context->aux_pids; aux; aux = aux->next) {
                struct audit_aux_data_pids *axs = (void *)aux;
-               int i;
 
                for (i = 0; i < axs->pid_count; i++)
                        if (audit_log_pid_context(context, axs->target_pid[i],
@@ -1371,8 +1382,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                        default:
                                /* log the name's directory component */
                                audit_log_format(ab, " name=");
-                               audit_log_n_untrustedstring(ab, n->name_len,
-                                                           n->name);
+                               audit_log_n_untrustedstring(ab, n->name,
+                                                           n->name_len);
                        }
                } else
                        audit_log_format(ab, " name=(null)");
@@ -1596,7 +1607,7 @@ static inline void handle_one(const struct inode *inode)
        if (likely(put_tree_ref(context, chunk)))
                return;
        if (unlikely(!grow_tree_refs(context))) {
-               printk(KERN_WARNING "out of memory, audit has lost a tree reference");
+               printk(KERN_WARNING "out of memory, audit has lost a tree reference\n");
                audit_set_auditable(context);
                audit_put_chunk(chunk);
                unroll_tree_refs(context, p, count);
@@ -1656,7 +1667,7 @@ retry:
                }
                /* too bad */
                printk(KERN_WARNING
-                       "out of memory, audit has lost a tree reference");
+                       "out of memory, audit has lost a tree reference\n");
                unroll_tree_refs(context, p, count);
                audit_set_auditable(context);
                return;
@@ -1752,13 +1763,13 @@ static int audit_inc_name_count(struct audit_context *context,
        if (context->name_count >= AUDIT_NAMES) {
                if (inode)
                        printk(KERN_DEBUG "name_count maxed, losing inode data: "
-                              "dev=%02x:%02x, inode=%lu",
+                              "dev=%02x:%02x, inode=%lu\n",
                               MAJOR(inode->i_sb->s_dev),
                               MINOR(inode->i_sb->s_dev),
                               inode->i_ino);
 
                else
-                       printk(KERN_DEBUG "name_count maxed, losing inode data");
+                       printk(KERN_DEBUG "name_count maxed, losing inode data\n");
                return 1;
        }
        context->name_count++;
@@ -2361,9 +2372,6 @@ int __audit_signal_info(int sig, struct task_struct *t)
        struct audit_aux_data_pids *axp;
        struct task_struct *tsk = current;
        struct audit_context *ctx = tsk->audit_context;
-       extern pid_t audit_sig_pid;
-       extern uid_t audit_sig_uid;
-       extern u32 audit_sig_sid;
 
        if (audit_pid && t->tgid == audit_pid) {
                if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) {
index c3c55544db2fb515c05c191bfc5c47c26b3cb62e..3c5301381837407d986f06cddaf665eca71fb412 100644 (file)
@@ -8,11 +8,7 @@
 /* Include headers that define the enum constants of interest */
 #include <linux/page-flags.h>
 #include <linux/mmzone.h>
-
-#define DEFINE(sym, val) \
-        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : : )
+#include <linux/kbuild.h>
 
 void foo(void)
 {
index 6d8de051382b0687ab1a449c245ebb2f05cd38f0..fbc6fc8949b4e718be405f500e977bb10841cf64 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/kmod.h>
 #include <linux/delayacct.h>
 #include <linux/cgroupstats.h>
+#include <linux/hash.h>
 
 #include <asm/atomic.h>
 
@@ -118,17 +119,7 @@ static int root_count;
  * be called.
  */
 static int need_forkexit_callback;
-
-/* bits in struct cgroup flags field */
-enum {
-       /* Control Group is dead */
-       CGRP_REMOVED,
-       /* Control Group has previously had a child cgroup or a task,
-        * but no longer (only if CGRP_NOTIFY_ON_RELEASE is set) */
-       CGRP_RELEASABLE,
-       /* Control Group requires release notifications to userspace */
-       CGRP_NOTIFY_ON_RELEASE,
-};
+static int need_mm_owner_callback __read_mostly;
 
 /* convenient tests for these bits */
 inline int cgroup_is_removed(const struct cgroup *cgrp)
@@ -204,6 +195,27 @@ static struct cg_cgroup_link init_css_set_link;
 static DEFINE_RWLOCK(css_set_lock);
 static int css_set_count;
 
+/* hash table for cgroup groups. This improves the performance to
+ * find an existing css_set */
+#define CSS_SET_HASH_BITS      7
+#define CSS_SET_TABLE_SIZE     (1 << CSS_SET_HASH_BITS)
+static struct hlist_head css_set_table[CSS_SET_TABLE_SIZE];
+
+static struct hlist_head *css_set_hash(struct cgroup_subsys_state *css[])
+{
+       int i;
+       int index;
+       unsigned long tmp = 0UL;
+
+       for (i = 0; i < CGROUP_SUBSYS_COUNT; i++)
+               tmp += (unsigned long)css[i];
+       tmp = (tmp >> 16) ^ tmp;
+
+       index = hash_long(tmp, CSS_SET_HASH_BITS);
+
+       return &css_set_table[index];
+}
+
 /* We don't maintain the lists running through each css_set to its
  * task until after the first call to cgroup_iter_start(). This
  * reduces the fork()/exit() overhead for people who have cgroups
@@ -230,7 +242,7 @@ static int use_task_css_set_links;
 static void unlink_css_set(struct css_set *cg)
 {
        write_lock(&css_set_lock);
-       list_del(&cg->list);
+       hlist_del(&cg->hlist);
        css_set_count--;
        while (!list_empty(&cg->cg_links)) {
                struct cg_cgroup_link *link;
@@ -295,9 +307,7 @@ static inline void put_css_set_taskexit(struct css_set *cg)
 /*
  * find_existing_css_set() is a helper for
  * find_css_set(), and checks to see whether an existing
- * css_set is suitable. This currently walks a linked-list for
- * simplicity; a later patch will use a hash table for better
- * performance
+ * css_set is suitable.
  *
  * oldcg: the cgroup group that we're using before the cgroup
  * transition
@@ -314,7 +324,9 @@ static struct css_set *find_existing_css_set(
 {
        int i;
        struct cgroupfs_root *root = cgrp->root;
-       struct list_head *l = &init_css_set.list;
+       struct hlist_head *hhead;
+       struct hlist_node *node;
+       struct css_set *cg;
 
        /* Built the set of subsystem state objects that we want to
         * see in the new css_set */
@@ -331,18 +343,13 @@ static struct css_set *find_existing_css_set(
                }
        }
 
-       /* Look through existing cgroup groups to find one to reuse */
-       do {
-               struct css_set *cg =
-                       list_entry(l, struct css_set, list);
-
+       hhead = css_set_hash(template);
+       hlist_for_each_entry(cg, node, hhead, hlist) {
                if (!memcmp(template, cg->subsys, sizeof(cg->subsys))) {
                        /* All subsystems matched */
                        return cg;
                }
-               /* Try the next cgroup group */
-               l = l->next;
-       } while (l != &init_css_set.list);
+       }
 
        /* No existing cgroup group matched */
        return NULL;
@@ -404,6 +411,8 @@ static struct css_set *find_css_set(
        struct list_head tmp_cg_links;
        struct cg_cgroup_link *link;
 
+       struct hlist_head *hhead;
+
        /* First see if we already have a cgroup group that matches
         * the desired set */
        write_lock(&css_set_lock);
@@ -428,6 +437,7 @@ static struct css_set *find_css_set(
        kref_init(&res->ref);
        INIT_LIST_HEAD(&res->cg_links);
        INIT_LIST_HEAD(&res->tasks);
+       INIT_HLIST_NODE(&res->hlist);
 
        /* Copy the set of subsystem state objects generated in
         * find_existing_css_set() */
@@ -467,9 +477,12 @@ static struct css_set *find_css_set(
 
        BUG_ON(!list_empty(&tmp_cg_links));
 
-       /* Link this cgroup group into the list */
-       list_add(&res->list, &init_css_set.list);
        css_set_count++;
+
+       /* Add this cgroup group to the hash table */
+       hhead = css_set_hash(res->subsys);
+       hlist_add_head(&res->hlist, hhead);
+
        write_unlock(&css_set_lock);
 
        return res;
@@ -562,7 +575,7 @@ static struct inode_operations cgroup_dir_inode_operations;
 static struct file_operations proc_cgroupstats_operations;
 
 static struct backing_dev_info cgroup_backing_dev_info = {
-       .capabilities   = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
+       .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK,
 };
 
 static struct inode *cgroup_new_inode(mode_t mode, struct super_block *sb)
@@ -948,7 +961,7 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
        int ret = 0;
        struct super_block *sb;
        struct cgroupfs_root *root;
-       struct list_head tmp_cg_links, *l;
+       struct list_head tmp_cg_links;
        INIT_LIST_HEAD(&tmp_cg_links);
 
        /* First find the desired set of subsystems */
@@ -990,6 +1003,7 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
                /* New superblock */
                struct cgroup *cgrp = &root->top_cgroup;
                struct inode *inode;
+               int i;
 
                BUG_ON(sb->s_root != NULL);
 
@@ -1034,22 +1048,25 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
                /* Link the top cgroup in this hierarchy into all
                 * the css_set objects */
                write_lock(&css_set_lock);
-               l = &init_css_set.list;
-               do {
+               for (i = 0; i < CSS_SET_TABLE_SIZE; i++) {
+                       struct hlist_head *hhead = &css_set_table[i];
+                       struct hlist_node *node;
                        struct css_set *cg;
-                       struct cg_cgroup_link *link;
-                       cg = list_entry(l, struct css_set, list);
-                       BUG_ON(list_empty(&tmp_cg_links));
-                       link = list_entry(tmp_cg_links.next,
-                                         struct cg_cgroup_link,
-                                         cgrp_link_list);
-                       list_del(&link->cgrp_link_list);
-                       link->cg = cg;
-                       list_add(&link->cgrp_link_list,
-                                &root->top_cgroup.css_sets);
-                       list_add(&link->cg_link_list, &cg->cg_links);
-                       l = l->next;
-               } while (l != &init_css_set.list);
+
+                       hlist_for_each_entry(cg, node, hhead, hlist) {
+                               struct cg_cgroup_link *link;
+
+                               BUG_ON(list_empty(&tmp_cg_links));
+                               link = list_entry(tmp_cg_links.next,
+                                                 struct cg_cgroup_link,
+                                                 cgrp_link_list);
+                               list_del(&link->cgrp_link_list);
+                               link->cg = cg;
+                               list_add(&link->cgrp_link_list,
+                                        &root->top_cgroup.css_sets);
+                               list_add(&link->cg_link_list, &cg->cg_links);
+                       }
+               }
                write_unlock(&css_set_lock);
 
                free_cg_links(&tmp_cg_links);
@@ -1307,18 +1324,16 @@ enum cgroup_filetype {
        FILE_DIR,
        FILE_TASKLIST,
        FILE_NOTIFY_ON_RELEASE,
-       FILE_RELEASABLE,
        FILE_RELEASE_AGENT,
 };
 
-static ssize_t cgroup_write_uint(struct cgroup *cgrp, struct cftype *cft,
-                                struct file *file,
-                                const char __user *userbuf,
-                                size_t nbytes, loff_t *unused_ppos)
+static ssize_t cgroup_write_X64(struct cgroup *cgrp, struct cftype *cft,
+                               struct file *file,
+                               const char __user *userbuf,
+                               size_t nbytes, loff_t *unused_ppos)
 {
        char buffer[64];
        int retval = 0;
-       u64 val;
        char *end;
 
        if (!nbytes)
@@ -1329,16 +1344,18 @@ static ssize_t cgroup_write_uint(struct cgroup *cgrp, struct cftype *cft,
                return -EFAULT;
 
        buffer[nbytes] = 0;     /* nul-terminate */
-
-       /* strip newline if necessary */
-       if (nbytes && (buffer[nbytes-1] == '\n'))
-               buffer[nbytes-1] = 0;
-       val = simple_strtoull(buffer, &end, 0);
-       if (*end)
-               return -EINVAL;
-
-       /* Pass to subsystem */
-       retval = cft->write_uint(cgrp, cft, val);
+       strstrip(buffer);
+       if (cft->write_u64) {
+               u64 val = simple_strtoull(buffer, &end, 0);
+               if (*end)
+                       return -EINVAL;
+               retval = cft->write_u64(cgrp, cft, val);
+       } else {
+               s64 val = simple_strtoll(buffer, &end, 0);
+               if (*end)
+                       return -EINVAL;
+               retval = cft->write_s64(cgrp, cft, val);
+       }
        if (!retval)
                retval = nbytes;
        return retval;
@@ -1419,23 +1436,39 @@ static ssize_t cgroup_file_write(struct file *file, const char __user *buf,
                return -ENODEV;
        if (cft->write)
                return cft->write(cgrp, cft, file, buf, nbytes, ppos);
-       if (cft->write_uint)
-               return cgroup_write_uint(cgrp, cft, file, buf, nbytes, ppos);
+       if (cft->write_u64 || cft->write_s64)
+               return cgroup_write_X64(cgrp, cft, file, buf, nbytes, ppos);
+       if (cft->trigger) {
+               int ret = cft->trigger(cgrp, (unsigned int)cft->private);
+               return ret ? ret : nbytes;
+       }
        return -EINVAL;
 }
 
-static ssize_t cgroup_read_uint(struct cgroup *cgrp, struct cftype *cft,
-                                  struct file *file,
-                                  char __user *buf, size_t nbytes,
-                                  loff_t *ppos)
+static ssize_t cgroup_read_u64(struct cgroup *cgrp, struct cftype *cft,
+                              struct file *file,
+                              char __user *buf, size_t nbytes,
+                              loff_t *ppos)
 {
        char tmp[64];
-       u64 val = cft->read_uint(cgrp, cft);
+       u64 val = cft->read_u64(cgrp, cft);
        int len = sprintf(tmp, "%llu\n", (unsigned long long) val);
 
        return simple_read_from_buffer(buf, nbytes, ppos, tmp, len);
 }
 
+static ssize_t cgroup_read_s64(struct cgroup *cgrp, struct cftype *cft,
+                              struct file *file,
+                              char __user *buf, size_t nbytes,
+                              loff_t *ppos)
+{
+       char tmp[64];
+       s64 val = cft->read_s64(cgrp, cft);
+       int len = sprintf(tmp, "%lld\n", (long long) val);
+
+       return simple_read_from_buffer(buf, nbytes, ppos, tmp, len);
+}
+
 static ssize_t cgroup_common_file_read(struct cgroup *cgrp,
                                          struct cftype *cft,
                                          struct file *file,
@@ -1490,11 +1523,56 @@ static ssize_t cgroup_file_read(struct file *file, char __user *buf,
 
        if (cft->read)
                return cft->read(cgrp, cft, file, buf, nbytes, ppos);
-       if (cft->read_uint)
-               return cgroup_read_uint(cgrp, cft, file, buf, nbytes, ppos);
+       if (cft->read_u64)
+               return cgroup_read_u64(cgrp, cft, file, buf, nbytes, ppos);
+       if (cft->read_s64)
+               return cgroup_read_s64(cgrp, cft, file, buf, nbytes, ppos);
        return -EINVAL;
 }
 
+/*
+ * seqfile ops/methods for returning structured data. Currently just
+ * supports string->u64 maps, but can be extended in future.
+ */
+
+struct cgroup_seqfile_state {
+       struct cftype *cft;
+       struct cgroup *cgroup;
+};
+
+static int cgroup_map_add(struct cgroup_map_cb *cb, const char *key, u64 value)
+{
+       struct seq_file *sf = cb->state;
+       return seq_printf(sf, "%s %llu\n", key, (unsigned long long)value);
+}
+
+static int cgroup_seqfile_show(struct seq_file *m, void *arg)
+{
+       struct cgroup_seqfile_state *state = m->private;
+       struct cftype *cft = state->cft;
+       if (cft->read_map) {
+               struct cgroup_map_cb cb = {
+                       .fill = cgroup_map_add,
+                       .state = m,
+               };
+               return cft->read_map(state->cgroup, cft, &cb);
+       }
+       return cft->read_seq_string(state->cgroup, cft, m);
+}
+
+int cgroup_seqfile_release(struct inode *inode, struct file *file)
+{
+       struct seq_file *seq = file->private_data;
+       kfree(seq->private);
+       return single_release(inode, file);
+}
+
+static struct file_operations cgroup_seqfile_operations = {
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = cgroup_seqfile_release,
+};
+
 static int cgroup_file_open(struct inode *inode, struct file *file)
 {
        int err;
@@ -1507,7 +1585,18 @@ static int cgroup_file_open(struct inode *inode, struct file *file)
        cft = __d_cft(file->f_dentry);
        if (!cft)
                return -ENODEV;
-       if (cft->open)
+       if (cft->read_map || cft->read_seq_string) {
+               struct cgroup_seqfile_state *state =
+                       kzalloc(sizeof(*state), GFP_USER);
+               if (!state)
+                       return -ENOMEM;
+               state->cft = cft;
+               state->cgroup = __d_cgrp(file->f_dentry->d_parent);
+               file->f_op = &cgroup_seqfile_operations;
+               err = single_open(file, cgroup_seqfile_show, state);
+               if (err < 0)
+                       kfree(state);
+       } else if (cft->open)
                err = cft->open(inode, file);
        else
                err = 0;
@@ -1715,7 +1804,7 @@ static void cgroup_advance_iter(struct cgroup *cgrp,
  * The tasklist_lock is not held here, as do_each_thread() and
  * while_each_thread() are protected by RCU.
  */
-void cgroup_enable_task_cg_lists(void)
+static void cgroup_enable_task_cg_lists(void)
 {
        struct task_struct *p, *g;
        write_lock(&css_set_lock);
@@ -1913,14 +2002,14 @@ int cgroup_scan_tasks(struct cgroup_scanner *scan)
 
        if (heap->size) {
                for (i = 0; i < heap->size; i++) {
-                       struct task_struct *p = heap->ptrs[i];
+                       struct task_struct *q = heap->ptrs[i];
                        if (i == 0) {
-                               latest_time = p->start_time;
-                               latest_task = p;
+                               latest_time = q->start_time;
+                               latest_task = q;
                        }
                        /* Process the task per the caller's callback */
-                       scan->process_task(p, scan);
-                       put_task_struct(p);
+                       scan->process_task(q, scan);
+                       put_task_struct(q);
                }
                /*
                 * If we had to process any tasks at all, scan again
@@ -2138,11 +2227,6 @@ static u64 cgroup_read_notify_on_release(struct cgroup *cgrp,
        return notify_on_release(cgrp);
 }
 
-static u64 cgroup_read_releasable(struct cgroup *cgrp, struct cftype *cft)
-{
-       return test_bit(CGRP_RELEASABLE, &cgrp->flags);
-}
-
 /*
  * for the common functions, 'private' gives the type of file
  */
@@ -2158,16 +2242,10 @@ static struct cftype files[] = {
 
        {
                .name = "notify_on_release",
-               .read_uint = cgroup_read_notify_on_release,
+               .read_u64 = cgroup_read_notify_on_release,
                .write = cgroup_common_file_write,
                .private = FILE_NOTIFY_ON_RELEASE,
        },
-
-       {
-               .name = "releasable",
-               .read_uint = cgroup_read_releasable,
-               .private = FILE_RELEASABLE,
-       }
 };
 
 static struct cftype cft_release_agent = {
@@ -2401,10 +2479,9 @@ static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry)
        return 0;
 }
 
-static void cgroup_init_subsys(struct cgroup_subsys *ss)
+static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
 {
        struct cgroup_subsys_state *css;
-       struct list_head *l;
 
        printk(KERN_INFO "Initializing cgroup subsys %s\n", ss->name);
 
@@ -2415,34 +2492,19 @@ static void cgroup_init_subsys(struct cgroup_subsys *ss)
        BUG_ON(IS_ERR(css));
        init_cgroup_css(css, ss, dummytop);
 
-       /* Update all cgroup groups to contain a subsys
+       /* Update the init_css_set to contain a subsys
         * pointer to this state - since the subsystem is
-        * newly registered, all tasks and hence all cgroup
-        * groups are in the subsystem's top cgroup. */
-       write_lock(&css_set_lock);
-       l = &init_css_set.list;
-       do {
-               struct css_set *cg =
-                       list_entry(l, struct css_set, list);
-               cg->subsys[ss->subsys_id] = dummytop->subsys[ss->subsys_id];
-               l = l->next;
-       } while (l != &init_css_set.list);
-       write_unlock(&css_set_lock);
-
-       /* If this subsystem requested that it be notified with fork
-        * events, we should send it one now for every process in the
-        * system */
-       if (ss->fork) {
-               struct task_struct *g, *p;
-
-               read_lock(&tasklist_lock);
-               do_each_thread(g, p) {
-                       ss->fork(ss, p);
-               } while_each_thread(g, p);
-               read_unlock(&tasklist_lock);
-       }
+        * newly registered, all tasks and hence the
+        * init_css_set is in the subsystem's top cgroup. */
+       init_css_set.subsys[ss->subsys_id] = dummytop->subsys[ss->subsys_id];
 
        need_forkexit_callback |= ss->fork || ss->exit;
+       need_mm_owner_callback |= !!ss->mm_owner_changed;
+
+       /* At system boot, before all subsystems have been
+        * registered, no tasks have been forked, so we don't
+        * need to invoke fork callbacks here. */
+       BUG_ON(!list_empty(&init_task.tasks));
 
        ss->active = 1;
 }
@@ -2458,9 +2520,9 @@ int __init cgroup_init_early(void)
        int i;
        kref_init(&init_css_set.ref);
        kref_get(&init_css_set.ref);
-       INIT_LIST_HEAD(&init_css_set.list);
        INIT_LIST_HEAD(&init_css_set.cg_links);
        INIT_LIST_HEAD(&init_css_set.tasks);
+       INIT_HLIST_NODE(&init_css_set.hlist);
        css_set_count = 1;
        init_cgroup_root(&rootnode);
        list_add(&rootnode.root_list, &roots);
@@ -2473,6 +2535,9 @@ int __init cgroup_init_early(void)
        list_add(&init_css_set_link.cg_link_list,
                 &init_css_set.cg_links);
 
+       for (i = 0; i < CSS_SET_TABLE_SIZE; i++)
+               INIT_HLIST_HEAD(&css_set_table[i]);
+
        for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
                struct cgroup_subsys *ss = subsys[i];
 
@@ -2502,7 +2567,7 @@ int __init cgroup_init(void)
 {
        int err;
        int i;
-       struct proc_dir_entry *entry;
+       struct hlist_head *hhead;
 
        err = bdi_init(&cgroup_backing_dev_info);
        if (err)
@@ -2514,13 +2579,15 @@ int __init cgroup_init(void)
                        cgroup_init_subsys(ss);
        }
 
+       /* Add init_css_set to the hash table */
+       hhead = css_set_hash(init_css_set.subsys);
+       hlist_add_head(&init_css_set.hlist, hhead);
+
        err = register_filesystem(&cgroup_fs_type);
        if (err < 0)
                goto out;
 
-       entry = create_proc_entry("cgroups", 0, NULL);
-       if (entry)
-               entry->proc_fops = &proc_cgroupstats_operations;
+       proc_create("cgroups", 0, NULL, &proc_cgroupstats_operations);
 
 out:
        if (err)
@@ -2683,6 +2750,34 @@ void cgroup_fork_callbacks(struct task_struct *child)
        }
 }
 
+#ifdef CONFIG_MM_OWNER
+/**
+ * cgroup_mm_owner_callbacks - run callbacks when the mm->owner changes
+ * @p: the new owner
+ *
+ * Called on every change to mm->owner. mm_init_owner() does not
+ * invoke this routine, since it assigns the mm->owner the first time
+ * and does not change it.
+ */
+void cgroup_mm_owner_callbacks(struct task_struct *old, struct task_struct *new)
+{
+       struct cgroup *oldcgrp, *newcgrp;
+
+       if (need_mm_owner_callback) {
+               int i;
+               for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
+                       struct cgroup_subsys *ss = subsys[i];
+                       oldcgrp = task_cgroup(old, ss->subsys_id);
+                       newcgrp = task_cgroup(new, ss->subsys_id);
+                       if (oldcgrp == newcgrp)
+                               continue;
+                       if (ss->mm_owner_changed)
+                               ss->mm_owner_changed(ss, oldcgrp, newcgrp);
+               }
+       }
+}
+#endif /* CONFIG_MM_OWNER */
+
 /**
  * cgroup_post_fork - called on a new task after adding it to the task list
  * @child: the task in question
index 37301e877cb03304ea06983c2766eef696b73892..c3dc3aba4c02a5b243b25b1ed7be971c5ec1ef17 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * kernel/ccontainer_debug.c - Example cgroup subsystem that
+ * kernel/cgroup_debug.c - Example cgroup subsystem that
  * exposes debug info
  *
  * Copyright (C) Google Inc, 2007
@@ -62,25 +62,35 @@ static u64 current_css_set_refcount_read(struct cgroup *cont,
        return count;
 }
 
+static u64 releasable_read(struct cgroup *cgrp, struct cftype *cft)
+{
+       return test_bit(CGRP_RELEASABLE, &cgrp->flags);
+}
+
 static struct cftype files[] =  {
        {
                .name = "cgroup_refcount",
-               .read_uint = cgroup_refcount_read,
+               .read_u64 = cgroup_refcount_read,
        },
        {
                .name = "taskcount",
-               .read_uint = taskcount_read,
+               .read_u64 = taskcount_read,
        },
 
        {
                .name = "current_css_set",
-               .read_uint = current_css_set_read,
+               .read_u64 = current_css_set_read,
        },
 
        {
                .name = "current_css_set_refcount",
-               .read_uint = current_css_set_refcount_read,
+               .read_u64 = current_css_set_refcount_read,
        },
+
+       {
+               .name = "releasable",
+               .read_u64 = releasable_read,
+       }
 };
 
 static int debug_populate(struct cgroup_subsys *ss, struct cgroup *cont)
index e1ef04870c2a12122fddfd3a712ed6e6d2a441ea..4a856a3643bb3f3ba3f99f6183bd8400b3f97eb9 100644 (file)
@@ -898,7 +898,7 @@ asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat
 
        current->state = TASK_INTERRUPTIBLE;
        schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
+       set_restore_sigmask();
        return -ERESTARTNOHAND;
 }
 #endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */
@@ -1080,4 +1080,3 @@ compat_sys_sysinfo(struct compat_sysinfo __user *info)
 
        return 0;
 }
-
index e84d3f9c6c7ba87218df59577462fc2523c0b6f9..4c345210ed8cca3ffb1c64a9e4aef92cf97eedf8 100644 (file)
@@ -79,12 +79,11 @@ static int __init ikconfig_init(void)
        struct proc_dir_entry *entry;
 
        /* create the current config file */
-       entry = create_proc_entry("config.gz", S_IFREG | S_IRUGO,
-                                 &proc_root);
+       entry = proc_create("config.gz", S_IFREG | S_IRUGO, NULL,
+                           &ikconfig_file_ops);
        if (!entry)
                return -ENOMEM;
 
-       entry->proc_fops = &ikconfig_file_ops;
        entry->size = kernel_config_data_size;
 
        return 0;
@@ -95,7 +94,7 @@ static int __init ikconfig_init(void)
 
 static void __exit ikconfig_cleanup(void)
 {
-       remove_proc_entry("config.gz", &proc_root);
+       remove_proc_entry("config.gz", NULL);
 }
 
 module_init(ikconfig_init);
index 2011ad8d26973fae39a373aa4121ea2fd3f0b8d1..c77bc3a1c7226b504be0a50f05136662dd464a73 100644 (file)
@@ -33,17 +33,13 @@ static struct {
         * an ongoing cpu hotplug operation.
         */
        int refcount;
-       wait_queue_head_t writer_queue;
 } cpu_hotplug;
 
-#define writer_exists() (cpu_hotplug.active_writer != NULL)
-
 void __init cpu_hotplug_init(void)
 {
        cpu_hotplug.active_writer = NULL;
        mutex_init(&cpu_hotplug.lock);
        cpu_hotplug.refcount = 0;
-       init_waitqueue_head(&cpu_hotplug.writer_queue);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -65,11 +61,8 @@ void put_online_cpus(void)
        if (cpu_hotplug.active_writer == current)
                return;
        mutex_lock(&cpu_hotplug.lock);
-       cpu_hotplug.refcount--;
-
-       if (unlikely(writer_exists()) && !cpu_hotplug.refcount)
-               wake_up(&cpu_hotplug.writer_queue);
-
+       if (!--cpu_hotplug.refcount && unlikely(cpu_hotplug.active_writer))
+               wake_up_process(cpu_hotplug.active_writer);
        mutex_unlock(&cpu_hotplug.lock);
 
 }
@@ -98,8 +91,8 @@ void cpu_maps_update_done(void)
  * Note that during a cpu-hotplug operation, the new readers, if any,
  * will be blocked by the cpu_hotplug.lock
  *
- * Since cpu_maps_update_begin is always called after invoking
- * cpu_maps_update_begin, we can be sure that only one writer is active.
+ * Since cpu_hotplug_begin() is always called after invoking
+ * cpu_maps_update_begin(), we can be sure that only one writer is active.
  *
  * Note that theoretically, there is a possibility of a livelock:
  * - Refcount goes to zero, last reader wakes up the sleeping
@@ -115,19 +108,16 @@ void cpu_maps_update_done(void)
  */
 static void cpu_hotplug_begin(void)
 {
-       DECLARE_WAITQUEUE(wait, current);
-
-       mutex_lock(&cpu_hotplug.lock);
-
        cpu_hotplug.active_writer = current;
-       add_wait_queue_exclusive(&cpu_hotplug.writer_queue, &wait);
-       while (cpu_hotplug.refcount) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
+
+       for (;;) {
+               mutex_lock(&cpu_hotplug.lock);
+               if (likely(!cpu_hotplug.refcount))
+                       break;
+               __set_current_state(TASK_UNINTERRUPTIBLE);
                mutex_unlock(&cpu_hotplug.lock);
                schedule();
-               mutex_lock(&cpu_hotplug.lock);
        }
-       remove_wait_queue_locked(&cpu_hotplug.writer_queue, &wait);
 }
 
 static void cpu_hotplug_done(void)
@@ -136,7 +126,7 @@ static void cpu_hotplug_done(void)
        mutex_unlock(&cpu_hotplug.lock);
 }
 /* Need to know about CPUs going up/down? */
-int __cpuinit register_cpu_notifier(struct notifier_block *nb)
+int __ref register_cpu_notifier(struct notifier_block *nb)
 {
        int ret;
        cpu_maps_update_begin();
@@ -149,7 +139,7 @@ int __cpuinit register_cpu_notifier(struct notifier_block *nb)
 
 EXPORT_SYMBOL(register_cpu_notifier);
 
-void unregister_cpu_notifier(struct notifier_block *nb)
+void __ref unregister_cpu_notifier(struct notifier_block *nb)
 {
        cpu_maps_update_begin();
        raw_notifier_chain_unregister(&cpu_chain, nb);
@@ -180,7 +170,7 @@ struct take_cpu_down_param {
 };
 
 /* Take this CPU down. */
-static int take_cpu_down(void *_param)
+static int __ref take_cpu_down(void *_param)
 {
        struct take_cpu_down_param *param = _param;
        int err;
@@ -199,7 +189,7 @@ static int take_cpu_down(void *_param)
 }
 
 /* Requires cpu_add_remove_lock to be held */
-static int _cpu_down(unsigned int cpu, int tasks_frozen)
+static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
 {
        int err, nr_calls = 0;
        struct task_struct *p;
@@ -225,7 +215,7 @@ static int _cpu_down(unsigned int cpu, int tasks_frozen)
                __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED | mod,
                                          hcpu, nr_calls, NULL);
                printk("%s: attempt to take down CPU %u failed\n",
-                               __FUNCTION__, cpu);
+                               __func__, cpu);
                err = -EINVAL;
                goto out_release;
        }
@@ -274,7 +264,7 @@ out_release:
        return err;
 }
 
-int cpu_down(unsigned int cpu)
+int __ref cpu_down(unsigned int cpu)
 {
        int err = 0;
 
@@ -305,7 +295,7 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen)
        if (ret == NOTIFY_BAD) {
                nr_calls--;
                printk("%s: attempt to bring up CPU %u failed\n",
-                               __FUNCTION__, cpu);
+                               __func__, cpu);
                ret = -EINVAL;
                goto out_notify;
        }
index 48a976c52cf58a5147d995c79544d2e2b16ab827..8da627d33804db7c9e30936fead573cedd4407e3 100644 (file)
@@ -127,6 +127,7 @@ struct cpuset_hotplug_scanner {
 typedef enum {
        CS_CPU_EXCLUSIVE,
        CS_MEM_EXCLUSIVE,
+       CS_MEM_HARDWALL,
        CS_MEMORY_MIGRATE,
        CS_SCHED_LOAD_BALANCE,
        CS_SPREAD_PAGE,
@@ -144,6 +145,11 @@ static inline int is_mem_exclusive(const struct cpuset *cs)
        return test_bit(CS_MEM_EXCLUSIVE, &cs->flags);
 }
 
+static inline int is_mem_hardwall(const struct cpuset *cs)
+{
+       return test_bit(CS_MEM_HARDWALL, &cs->flags);
+}
+
 static inline int is_sched_load_balance(const struct cpuset *cs)
 {
        return test_bit(CS_SCHED_LOAD_BALANCE, &cs->flags);
@@ -735,7 +741,8 @@ static inline int started_after(void *p1, void *p2)
  * Return nonzero if this tasks's cpus_allowed mask should be changed (in other
  * words, if its mask is not equal to its cpuset's mask).
  */
-int cpuset_test_cpumask(struct task_struct *tsk, struct cgroup_scanner *scan)
+static int cpuset_test_cpumask(struct task_struct *tsk,
+                              struct cgroup_scanner *scan)
 {
        return !cpus_equal(tsk->cpus_allowed,
                        (cgroup_cs(scan->cg))->cpus_allowed);
@@ -752,7 +759,8 @@ int cpuset_test_cpumask(struct task_struct *tsk, struct cgroup_scanner *scan)
  * We don't need to re-check for the cgroup/cpuset membership, since we're
  * holding cgroup_lock() at this point.
  */
-void cpuset_change_cpumask(struct task_struct *tsk, struct cgroup_scanner *scan)
+static void cpuset_change_cpumask(struct task_struct *tsk,
+                                 struct cgroup_scanner *scan)
 {
        set_cpus_allowed_ptr(tsk, &((cgroup_cs(scan->cg))->cpus_allowed));
 }
@@ -1023,19 +1031,6 @@ int current_cpuset_is_being_rebound(void)
        return task_cs(current) == cpuset_being_rebound;
 }
 
-/*
- * Call with cgroup_mutex held.
- */
-
-static int update_memory_pressure_enabled(struct cpuset *cs, char *buf)
-{
-       if (simple_strtoul(buf, NULL, 10) != 0)
-               cpuset_memory_pressure_enabled = 1;
-       else
-               cpuset_memory_pressure_enabled = 0;
-       return 0;
-}
-
 static int update_relax_domain_level(struct cpuset *cs, char *buf)
 {
        int val = simple_strtol(buf, NULL, 10);
@@ -1053,25 +1048,20 @@ static int update_relax_domain_level(struct cpuset *cs, char *buf)
 
 /*
  * update_flag - read a 0 or a 1 in a file and update associated flag
- * bit:        the bit to update (CS_CPU_EXCLUSIVE, CS_MEM_EXCLUSIVE,
- *                             CS_SCHED_LOAD_BALANCE,
- *                             CS_NOTIFY_ON_RELEASE, CS_MEMORY_MIGRATE,
- *                             CS_SPREAD_PAGE, CS_SPREAD_SLAB)
- * cs: the cpuset to update
- * buf:        the buffer where we read the 0 or 1
+ * bit:                the bit to update (see cpuset_flagbits_t)
+ * cs:         the cpuset to update
+ * turning_on:         whether the flag is being set or cleared
  *
  * Call with cgroup_mutex held.
  */
 
-static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf)
+static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
+                      int turning_on)
 {
-       int turning_on;
        struct cpuset trialcs;
        int err;
        int cpus_nonempty, balance_flag_changed;
 
-       turning_on = (simple_strtoul(buf, NULL, 10) != 0);
-
        trialcs = *cs;
        if (turning_on)
                set_bit(bit, &trialcs.flags);
@@ -1241,6 +1231,7 @@ typedef enum {
        FILE_MEMLIST,
        FILE_CPU_EXCLUSIVE,
        FILE_MEM_EXCLUSIVE,
+       FILE_MEM_HARDWALL,
        FILE_SCHED_LOAD_BALANCE,
        FILE_SCHED_RELAX_DOMAIN_LEVEL,
        FILE_MEMORY_PRESSURE_ENABLED,
@@ -1289,46 +1280,71 @@ static ssize_t cpuset_common_file_write(struct cgroup *cont,
        case FILE_MEMLIST:
                retval = update_nodemask(cs, buffer);
                break;
+       case FILE_SCHED_RELAX_DOMAIN_LEVEL:
+               retval = update_relax_domain_level(cs, buffer);
+               break;
+       default:
+               retval = -EINVAL;
+               goto out2;
+       }
+
+       if (retval == 0)
+               retval = nbytes;
+out2:
+       cgroup_unlock();
+out1:
+       kfree(buffer);
+       return retval;
+}
+
+static int cpuset_write_u64(struct cgroup *cgrp, struct cftype *cft, u64 val)
+{
+       int retval = 0;
+       struct cpuset *cs = cgroup_cs(cgrp);
+       cpuset_filetype_t type = cft->private;
+
+       cgroup_lock();
+
+       if (cgroup_is_removed(cgrp)) {
+               cgroup_unlock();
+               return -ENODEV;
+       }
+
+       switch (type) {
        case FILE_CPU_EXCLUSIVE:
-               retval = update_flag(CS_CPU_EXCLUSIVE, cs, buffer);
+               retval = update_flag(CS_CPU_EXCLUSIVE, cs, val);
                break;
        case FILE_MEM_EXCLUSIVE:
-               retval = update_flag(CS_MEM_EXCLUSIVE, cs, buffer);
+               retval = update_flag(CS_MEM_EXCLUSIVE, cs, val);
                break;
-       case FILE_SCHED_LOAD_BALANCE:
-               retval = update_flag(CS_SCHED_LOAD_BALANCE, cs, buffer);
+       case FILE_MEM_HARDWALL:
+               retval = update_flag(CS_MEM_HARDWALL, cs, val);
                break;
-       case FILE_SCHED_RELAX_DOMAIN_LEVEL:
-               retval = update_relax_domain_level(cs, buffer);
+       case FILE_SCHED_LOAD_BALANCE:
+               retval = update_flag(CS_SCHED_LOAD_BALANCE, cs, val);
                break;
        case FILE_MEMORY_MIGRATE:
-               retval = update_flag(CS_MEMORY_MIGRATE, cs, buffer);
+               retval = update_flag(CS_MEMORY_MIGRATE, cs, val);
                break;
        case FILE_MEMORY_PRESSURE_ENABLED:
-               retval = update_memory_pressure_enabled(cs, buffer);
+               cpuset_memory_pressure_enabled = !!val;
                break;
        case FILE_MEMORY_PRESSURE:
                retval = -EACCES;
                break;
        case FILE_SPREAD_PAGE:
-               retval = update_flag(CS_SPREAD_PAGE, cs, buffer);
+               retval = update_flag(CS_SPREAD_PAGE, cs, val);
                cs->mems_generation = cpuset_mems_generation++;
                break;
        case FILE_SPREAD_SLAB:
-               retval = update_flag(CS_SPREAD_SLAB, cs, buffer);
+               retval = update_flag(CS_SPREAD_SLAB, cs, val);
                cs->mems_generation = cpuset_mems_generation++;
                break;
        default:
                retval = -EINVAL;
-               goto out2;
+               break;
        }
-
-       if (retval == 0)
-               retval = nbytes;
-out2:
        cgroup_unlock();
-out1:
-       kfree(buffer);
        return retval;
 }
 
@@ -1390,33 +1406,9 @@ static ssize_t cpuset_common_file_read(struct cgroup *cont,
        case FILE_MEMLIST:
                s += cpuset_sprintf_memlist(s, cs);
                break;
-       case FILE_CPU_EXCLUSIVE:
-               *s++ = is_cpu_exclusive(cs) ? '1' : '0';
-               break;
-       case FILE_MEM_EXCLUSIVE:
-               *s++ = is_mem_exclusive(cs) ? '1' : '0';
-               break;
-       case FILE_SCHED_LOAD_BALANCE:
-               *s++ = is_sched_load_balance(cs) ? '1' : '0';
-               break;
        case FILE_SCHED_RELAX_DOMAIN_LEVEL:
                s += sprintf(s, "%d", cs->relax_domain_level);
                break;
-       case FILE_MEMORY_MIGRATE:
-               *s++ = is_memory_migrate(cs) ? '1' : '0';
-               break;
-       case FILE_MEMORY_PRESSURE_ENABLED:
-               *s++ = cpuset_memory_pressure_enabled ? '1' : '0';
-               break;
-       case FILE_MEMORY_PRESSURE:
-               s += sprintf(s, "%d", fmeter_getrate(&cs->fmeter));
-               break;
-       case FILE_SPREAD_PAGE:
-               *s++ = is_spread_page(cs) ? '1' : '0';
-               break;
-       case FILE_SPREAD_SLAB:
-               *s++ = is_spread_slab(cs) ? '1' : '0';
-               break;
        default:
                retval = -EINVAL;
                goto out;
@@ -1429,121 +1421,137 @@ out:
        return retval;
 }
 
-
-
+static u64 cpuset_read_u64(struct cgroup *cont, struct cftype *cft)
+{
+       struct cpuset *cs = cgroup_cs(cont);
+       cpuset_filetype_t type = cft->private;
+       switch (type) {
+       case FILE_CPU_EXCLUSIVE:
+               return is_cpu_exclusive(cs);
+       case FILE_MEM_EXCLUSIVE:
+               return is_mem_exclusive(cs);
+       case FILE_MEM_HARDWALL:
+               return is_mem_hardwall(cs);
+       case FILE_SCHED_LOAD_BALANCE:
+               return is_sched_load_balance(cs);
+       case FILE_MEMORY_MIGRATE:
+               return is_memory_migrate(cs);
+       case FILE_MEMORY_PRESSURE_ENABLED:
+               return cpuset_memory_pressure_enabled;
+       case FILE_MEMORY_PRESSURE:
+               return fmeter_getrate(&cs->fmeter);
+       case FILE_SPREAD_PAGE:
+               return is_spread_page(cs);
+       case FILE_SPREAD_SLAB:
+               return is_spread_slab(cs);
+       default:
+               BUG();
+       }
+}
 
 
 /*
  * for the common functions, 'private' gives the type of file
  */
 
-static struct cftype cft_cpus = {
-       .name = "cpus",
-       .read = cpuset_common_file_read,
-       .write = cpuset_common_file_write,
-       .private = FILE_CPULIST,
-};
-
-static struct cftype cft_mems = {
-       .name = "mems",
-       .read = cpuset_common_file_read,
-       .write = cpuset_common_file_write,
-       .private = FILE_MEMLIST,
-};
-
-static struct cftype cft_cpu_exclusive = {
-       .name = "cpu_exclusive",
-       .read = cpuset_common_file_read,
-       .write = cpuset_common_file_write,
-       .private = FILE_CPU_EXCLUSIVE,
-};
-
-static struct cftype cft_mem_exclusive = {
-       .name = "mem_exclusive",
-       .read = cpuset_common_file_read,
-       .write = cpuset_common_file_write,
-       .private = FILE_MEM_EXCLUSIVE,
-};
-
-static struct cftype cft_sched_load_balance = {
-       .name = "sched_load_balance",
-       .read = cpuset_common_file_read,
-       .write = cpuset_common_file_write,
-       .private = FILE_SCHED_LOAD_BALANCE,
-};
-
-static struct cftype cft_sched_relax_domain_level = {
-       .name = "sched_relax_domain_level",
-       .read = cpuset_common_file_read,
-       .write = cpuset_common_file_write,
-       .private = FILE_SCHED_RELAX_DOMAIN_LEVEL,
-};
-
-static struct cftype cft_memory_migrate = {
-       .name = "memory_migrate",
-       .read = cpuset_common_file_read,
-       .write = cpuset_common_file_write,
-       .private = FILE_MEMORY_MIGRATE,
+static struct cftype files[] = {
+       {
+               .name = "cpus",
+               .read = cpuset_common_file_read,
+               .write = cpuset_common_file_write,
+               .private = FILE_CPULIST,
+       },
+
+       {
+               .name = "mems",
+               .read = cpuset_common_file_read,
+               .write = cpuset_common_file_write,
+               .private = FILE_MEMLIST,
+       },
+
+       {
+               .name = "cpu_exclusive",
+               .read_u64 = cpuset_read_u64,
+               .write_u64 = cpuset_write_u64,
+               .private = FILE_CPU_EXCLUSIVE,
+       },
+
+       {
+               .name = "mem_exclusive",
+               .read_u64 = cpuset_read_u64,
+               .write_u64 = cpuset_write_u64,
+               .private = FILE_MEM_EXCLUSIVE,
+       },
+
+       {
+               .name = "mem_hardwall",
+               .read_u64 = cpuset_read_u64,
+               .write_u64 = cpuset_write_u64,
+               .private = FILE_MEM_HARDWALL,
+       },
+
+       {
+               .name = "sched_load_balance",
+               .read_u64 = cpuset_read_u64,
+               .write_u64 = cpuset_write_u64,
+               .private = FILE_SCHED_LOAD_BALANCE,
+       },
+
+       {
+               .name = "sched_relax_domain_level",
+               .read_u64 = cpuset_read_u64,
+               .write_u64 = cpuset_write_u64,
+               .private = FILE_SCHED_RELAX_DOMAIN_LEVEL,
+       },
+
+       {
+               .name = "memory_migrate",
+               .read_u64 = cpuset_read_u64,
+               .write_u64 = cpuset_write_u64,
+               .private = FILE_MEMORY_MIGRATE,
+       },
+
+       {
+               .name = "memory_pressure",
+               .read_u64 = cpuset_read_u64,
+               .write_u64 = cpuset_write_u64,
+               .private = FILE_MEMORY_PRESSURE,
+       },
+
+       {
+               .name = "memory_spread_page",
+               .read_u64 = cpuset_read_u64,
+               .write_u64 = cpuset_write_u64,
+               .private = FILE_SPREAD_PAGE,
+       },
+
+       {
+               .name = "memory_spread_slab",
+               .read_u64 = cpuset_read_u64,
+               .write_u64 = cpuset_write_u64,
+               .private = FILE_SPREAD_SLAB,
+       },
 };
 
 static struct cftype cft_memory_pressure_enabled = {
        .name = "memory_pressure_enabled",
-       .read = cpuset_common_file_read,
-       .write = cpuset_common_file_write,
+       .read_u64 = cpuset_read_u64,
+       .write_u64 = cpuset_write_u64,
        .private = FILE_MEMORY_PRESSURE_ENABLED,
 };
 
-static struct cftype cft_memory_pressure = {
-       .name = "memory_pressure",
-       .read = cpuset_common_file_read,
-       .write = cpuset_common_file_write,
-       .private = FILE_MEMORY_PRESSURE,
-};
-
-static struct cftype cft_spread_page = {
-       .name = "memory_spread_page",
-       .read = cpuset_common_file_read,
-       .write = cpuset_common_file_write,
-       .private = FILE_SPREAD_PAGE,
-};
-
-static struct cftype cft_spread_slab = {
-       .name = "memory_spread_slab",
-       .read = cpuset_common_file_read,
-       .write = cpuset_common_file_write,
-       .private = FILE_SPREAD_SLAB,
-};
-
 static int cpuset_populate(struct cgroup_subsys *ss, struct cgroup *cont)
 {
        int err;
 
-       if ((err = cgroup_add_file(cont, ss, &cft_cpus)) < 0)
-               return err;
-       if ((err = cgroup_add_file(cont, ss, &cft_mems)) < 0)
-               return err;
-       if ((err = cgroup_add_file(cont, ss, &cft_cpu_exclusive)) < 0)
-               return err;
-       if ((err = cgroup_add_file(cont, ss, &cft_mem_exclusive)) < 0)
-               return err;
-       if ((err = cgroup_add_file(cont, ss, &cft_memory_migrate)) < 0)
-               return err;
-       if ((err = cgroup_add_file(cont, ss, &cft_sched_load_balance)) < 0)
-               return err;
-       if ((err = cgroup_add_file(cont, ss,
-                                       &cft_sched_relax_domain_level)) < 0)
-               return err;
-       if ((err = cgroup_add_file(cont, ss, &cft_memory_pressure)) < 0)
-               return err;
-       if ((err = cgroup_add_file(cont, ss, &cft_spread_page)) < 0)
-               return err;
-       if ((err = cgroup_add_file(cont, ss, &cft_spread_slab)) < 0)
+       err = cgroup_add_files(cont, ss, files, ARRAY_SIZE(files));
+       if (err)
                return err;
        /* memory_pressure_enabled is in root cpuset only */
-       if (err == 0 && !cont->parent)
+       if (!cont->parent)
                err = cgroup_add_file(cont, ss,
-                                        &cft_memory_pressure_enabled);
-       return 0;
+                                     &cft_memory_pressure_enabled);
+       return err;
 }
 
 /*
@@ -1643,7 +1651,7 @@ static void cpuset_destroy(struct cgroup_subsys *ss, struct cgroup *cont)
        cpuset_update_task_memory_state();
 
        if (is_sched_load_balance(cs))
-               update_flag(CS_SCHED_LOAD_BALANCE, cs, "0");
+               update_flag(CS_SCHED_LOAD_BALANCE, cs, 0);
 
        number_of_cpusets--;
        kfree(cs);
@@ -1708,7 +1716,8 @@ int __init cpuset_init(void)
  * Called by cgroup_scan_tasks() for each task in a cgroup.
  * Return nonzero to stop the walk through the tasks.
  */
-void cpuset_do_move_task(struct task_struct *tsk, struct cgroup_scanner *scan)
+static void cpuset_do_move_task(struct task_struct *tsk,
+                               struct cgroup_scanner *scan)
 {
        struct cpuset_hotplug_scanner *chsp;
 
@@ -1970,14 +1979,14 @@ int cpuset_nodemask_valid_mems_allowed(nodemask_t *nodemask)
 }
 
 /*
- * nearest_exclusive_ancestor() - Returns the nearest mem_exclusive
- * ancestor to the specified cpuset.  Call holding callback_mutex.
- * If no ancestor is mem_exclusive (an unusual configuration), then
- * returns the root cpuset.
+ * nearest_hardwall_ancestor() - Returns the nearest mem_exclusive or
+ * mem_hardwall ancestor to the specified cpuset.  Call holding
+ * callback_mutex.  If no ancestor is mem_exclusive or mem_hardwall
+ * (an unusual configuration), then returns the root cpuset.
  */
-static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs)
+static const struct cpuset *nearest_hardwall_ancestor(const struct cpuset *cs)
 {
-       while (!is_mem_exclusive(cs) && cs->parent)
+       while (!(is_mem_exclusive(cs) || is_mem_hardwall(cs)) && cs->parent)
                cs = cs->parent;
        return cs;
 }
@@ -1991,7 +2000,7 @@ static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs)
  * __GFP_THISNODE is set, yes, we can always allocate.  If zone
  * z's node is in our tasks mems_allowed, yes.  If it's not a
  * __GFP_HARDWALL request and this zone's nodes is in the nearest
- * mem_exclusive cpuset ancestor to this tasks cpuset, yes.
+ * hardwalled cpuset ancestor to this tasks cpuset, yes.
  * If the task has been OOM killed and has access to memory reserves
  * as specified by the TIF_MEMDIE flag, yes.
  * Otherwise, no.
@@ -2014,7 +2023,7 @@ static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs)
  * and do not allow allocations outside the current tasks cpuset
  * unless the task has been OOM killed as is marked TIF_MEMDIE.
  * GFP_KERNEL allocations are not so marked, so can escape to the
- * nearest enclosing mem_exclusive ancestor cpuset.
+ * nearest enclosing hardwalled ancestor cpuset.
  *
  * Scanning up parent cpusets requires callback_mutex.  The
  * __alloc_pages() routine only calls here with __GFP_HARDWALL bit
@@ -2037,7 +2046,7 @@ static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs)
  *     in_interrupt - any node ok (current task context irrelevant)
  *     GFP_ATOMIC   - any node ok
  *     TIF_MEMDIE   - any node ok
- *     GFP_KERNEL   - any node in enclosing mem_exclusive cpuset ok
+ *     GFP_KERNEL   - any node in enclosing hardwalled cpuset ok
  *     GFP_USER     - only nodes in current tasks mems allowed ok.
  *
  * Rule:
@@ -2074,7 +2083,7 @@ int __cpuset_zone_allowed_softwall(struct zone *z, gfp_t gfp_mask)
        mutex_lock(&callback_mutex);
 
        task_lock(current);
-       cs = nearest_exclusive_ancestor(task_cs(current));
+       cs = nearest_hardwall_ancestor(task_cs(current));
        task_unlock(current);
 
        allowed = node_isset(node, cs->mems_allowed);
index 6a82bb716dace9bbcf0b469e3119fd10a95b9b1a..d2c60a82279085e80d0a46edbc0a3557e9b87f83 100644 (file)
@@ -149,12 +149,7 @@ static const struct file_operations proc_dma_operations = {
 
 static int __init proc_dma_init(void)
 {
-       struct proc_dir_entry *e;
-
-       e = create_proc_entry("dma", 0, NULL);
-       if (e)
-               e->proc_fops = &proc_dma_operations;
-
+       proc_create("dma", 0, NULL, &proc_dma_operations);
        return 0;
 }
 
index 2a9d98c641ac4926eafc8a06312625fbd6218080..d3ad54677f9c0257fa0a373f8ce1b4774e947722 100644 (file)
 
 static void exit_mm(struct task_struct * tsk);
 
+static inline int task_detached(struct task_struct *p)
+{
+       return p->exit_signal == -1;
+}
+
 static void __unhash_process(struct task_struct *p)
 {
        nr_threads--;
@@ -160,7 +165,7 @@ repeat:
        zap_leader = 0;
        leader = p->group_leader;
        if (leader != p && thread_group_empty(leader) && leader->exit_state == EXIT_ZOMBIE) {
-               BUG_ON(leader->exit_signal == -1);
+               BUG_ON(task_detached(leader));
                do_notify_parent(leader, leader->exit_signal);
                /*
                 * If we were the last child thread and the leader has
@@ -170,7 +175,7 @@ repeat:
                 * do_notify_parent() will have marked it self-reaping in
                 * that case.
                 */
-               zap_leader = (leader->exit_signal == -1);
+               zap_leader = task_detached(leader);
        }
 
        write_unlock_irq(&tasklist_lock);
@@ -329,13 +334,11 @@ void __set_special_pids(struct pid *pid)
        pid_t nr = pid_nr(pid);
 
        if (task_session(curr) != pid) {
-               detach_pid(curr, PIDTYPE_SID);
-               attach_pid(curr, PIDTYPE_SID, pid);
+               change_pid(curr, PIDTYPE_SID, pid);
                set_task_session(curr, nr);
        }
        if (task_pgrp(curr) != pid) {
-               detach_pid(curr, PIDTYPE_PGID);
-               attach_pid(curr, PIDTYPE_PGID, pid);
+               change_pid(curr, PIDTYPE_PGID, pid);
                set_task_pgrp(curr, nr);
        }
 }
@@ -557,6 +560,88 @@ void exit_fs(struct task_struct *tsk)
 
 EXPORT_SYMBOL_GPL(exit_fs);
 
+#ifdef CONFIG_MM_OWNER
+/*
+ * Task p is exiting and it owned mm, lets find a new owner for it
+ */
+static inline int
+mm_need_new_owner(struct mm_struct *mm, struct task_struct *p)
+{
+       /*
+        * If there are other users of the mm and the owner (us) is exiting
+        * we need to find a new owner to take on the responsibility.
+        */
+       if (!mm)
+               return 0;
+       if (atomic_read(&mm->mm_users) <= 1)
+               return 0;
+       if (mm->owner != p)
+               return 0;
+       return 1;
+}
+
+void mm_update_next_owner(struct mm_struct *mm)
+{
+       struct task_struct *c, *g, *p = current;
+
+retry:
+       if (!mm_need_new_owner(mm, p))
+               return;
+
+       read_lock(&tasklist_lock);
+       /*
+        * Search in the children
+        */
+       list_for_each_entry(c, &p->children, sibling) {
+               if (c->mm == mm)
+                       goto assign_new_owner;
+       }
+
+       /*
+        * Search in the siblings
+        */
+       list_for_each_entry(c, &p->parent->children, sibling) {
+               if (c->mm == mm)
+                       goto assign_new_owner;
+       }
+
+       /*
+        * Search through everything else. We should not get
+        * here often
+        */
+       do_each_thread(g, c) {
+               if (c->mm == mm)
+                       goto assign_new_owner;
+       } while_each_thread(g, c);
+
+       read_unlock(&tasklist_lock);
+       return;
+
+assign_new_owner:
+       BUG_ON(c == p);
+       get_task_struct(c);
+       /*
+        * The task_lock protects c->mm from changing.
+        * We always want mm->owner->mm == mm
+        */
+       task_lock(c);
+       /*
+        * Delay read_unlock() till we have the task_lock()
+        * to ensure that c does not slip away underneath us
+        */
+       read_unlock(&tasklist_lock);
+       if (c->mm != mm) {
+               task_unlock(c);
+               put_task_struct(c);
+               goto retry;
+       }
+       cgroup_mm_owner_callbacks(mm->owner, c);
+       mm->owner = c;
+       task_unlock(c);
+       put_task_struct(c);
+}
+#endif /* CONFIG_MM_OWNER */
+
 /*
  * Turn us into a lazy TLB process if we
  * aren't already..
@@ -596,6 +681,7 @@ static void exit_mm(struct task_struct * tsk)
        /* We don't want this task to be frozen prematurely */
        clear_freeze_flag(tsk);
        task_unlock(tsk);
+       mm_update_next_owner(mm);
        mmput(mm);
 }
 
@@ -610,7 +696,7 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
        if (unlikely(traced)) {
                /* Preserve ptrace links if someone else is tracing this child.  */
                list_del_init(&p->ptrace_list);
-               if (p->parent != p->real_parent)
+               if (ptrace_reparented(p))
                        list_add(&p->ptrace_list, &p->real_parent->ptrace_children);
        } else {
                /* If this child is being traced, then we're the one tracing it
@@ -634,18 +720,18 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
        /* If this is a threaded reparent there is no need to
         * notify anyone anything has happened.
         */
-       if (p->real_parent->group_leader == father->group_leader)
+       if (same_thread_group(p->real_parent, father))
                return;
 
        /* We don't want people slaying init.  */
-       if (p->exit_signal != -1)
+       if (!task_detached(p))
                p->exit_signal = SIGCHLD;
 
        /* If we'd notified the old parent about this child's death,
         * also notify the new parent.
         */
        if (!traced && p->exit_state == EXIT_ZOMBIE &&
-           p->exit_signal != -1 && thread_group_empty(p))
+           !task_detached(p) && thread_group_empty(p))
                do_notify_parent(p, p->exit_signal);
 
        kill_orphaned_pgrp(p, father);
@@ -698,18 +784,18 @@ static void forget_original_parent(struct task_struct *father)
                } else {
                        /* reparent ptraced task to its real parent */
                        __ptrace_unlink (p);
-                       if (p->exit_state == EXIT_ZOMBIE && p->exit_signal != -1 &&
+                       if (p->exit_state == EXIT_ZOMBIE && !task_detached(p) &&
                            thread_group_empty(p))
                                do_notify_parent(p, p->exit_signal);
                }
 
                /*
-                * if the ptraced child is a zombie with exit_signal == -1
-                * we must collect it before we exit, or it will remain
-                * zombie forever since we prevented it from self-reap itself
-                * while it was being traced by us, to be able to see it in wait4.
+                * if the ptraced child is a detached zombie we must collect
+                * it before we exit, or it will remain zombie forever since
+                * we prevented it from self-reap itself while it was being
+                * traced by us, to be able to see it in wait4.
                 */
-               if (unlikely(ptrace && p->exit_state == EXIT_ZOMBIE && p->exit_signal == -1))
+               if (unlikely(ptrace && p->exit_state == EXIT_ZOMBIE && task_detached(p)))
                        list_add(&p->ptrace_list, &ptrace_dead);
        }
 
@@ -766,29 +852,30 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
         * we have changed execution domain as these two values started
         * the same after a fork.
         */
-       if (tsk->exit_signal != SIGCHLD && tsk->exit_signal != -1 &&
+       if (tsk->exit_signal != SIGCHLD && !task_detached(tsk) &&
            (tsk->parent_exec_id != tsk->real_parent->self_exec_id ||
-            tsk->self_exec_id != tsk->parent_exec_id)
-           && !capable(CAP_KILL))
+            tsk->self_exec_id != tsk->parent_exec_id) &&
+           !capable(CAP_KILL))
                tsk->exit_signal = SIGCHLD;
 
-
        /* If something other than our normal parent is ptracing us, then
         * send it a SIGCHLD instead of honoring exit_signal.  exit_signal
         * only has special meaning to our real parent.
         */
-       if (tsk->exit_signal != -1 && thread_group_empty(tsk)) {
-               int signal = tsk->parent == tsk->real_parent ? tsk->exit_signal : SIGCHLD;
+       if (!task_detached(tsk) && thread_group_empty(tsk)) {
+               int signal = ptrace_reparented(tsk) ?
+                               SIGCHLD : tsk->exit_signal;
                do_notify_parent(tsk, signal);
        } else if (tsk->ptrace) {
                do_notify_parent(tsk, SIGCHLD);
        }
 
        state = EXIT_ZOMBIE;
-       if (tsk->exit_signal == -1 && likely(!tsk->ptrace))
+       if (task_detached(tsk) && likely(!tsk->ptrace))
                state = EXIT_DEAD;
        tsk->exit_state = state;
 
+       /* mt-exec, de_thread() is waiting for us */
        if (thread_group_leader(tsk) &&
            tsk->signal->notify_count < 0 &&
            tsk->signal->group_exit_task)
@@ -1032,12 +1119,13 @@ asmlinkage long sys_exit(int error_code)
 NORET_TYPE void
 do_group_exit(int exit_code)
 {
+       struct signal_struct *sig = current->signal;
+
        BUG_ON(exit_code & 0x80); /* core dumps don't get here */
 
-       if (current->signal->flags & SIGNAL_GROUP_EXIT)
-               exit_code = current->signal->group_exit_code;
+       if (signal_group_exit(sig))
+               exit_code = sig->group_exit_code;
        else if (!thread_group_empty(current)) {
-               struct signal_struct *const sig = current->signal;
                struct sighand_struct *const sighand = current->sighand;
                spin_lock_irq(&sighand->siglock);
                if (signal_group_exit(sig))
@@ -1089,7 +1177,7 @@ static int eligible_child(enum pid_type type, struct pid *pid, int options,
         * Do not consider detached threads that are
         * not ptraced:
         */
-       if (p->exit_signal == -1 && !p->ptrace)
+       if (task_detached(p) && !p->ptrace)
                return 0;
 
        /* Wait for all children (clone and not) if __WALL is set;
@@ -1179,8 +1267,7 @@ static int wait_task_zombie(struct task_struct *p, int noreap,
                return 0;
        }
 
-       /* traced means p->ptrace, but not vice versa */
-       traced = (p->real_parent != p->parent);
+       traced = ptrace_reparented(p);
 
        if (likely(!traced)) {
                struct signal_struct *psig;
@@ -1281,9 +1368,9 @@ static int wait_task_zombie(struct task_struct *p, int noreap,
                 * If it's still not detached after that, don't release
                 * it now.
                 */
-               if (p->exit_signal != -1) {
+               if (!task_detached(p)) {
                        do_notify_parent(p, p->exit_signal);
-                       if (p->exit_signal != -1) {
+                       if (!task_detached(p)) {
                                p->exit_state = EXIT_ZOMBIE;
                                p = NULL;
                        }
index 6067e429f2816ecd71990c4991354933d129502f..2bb675af4de30908b2dd1a22e745541e2bcbc3f5 100644 (file)
@@ -381,14 +381,13 @@ static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p)
        mm->ioctx_list = NULL;
        mm->free_area_cache = TASK_UNMAPPED_BASE;
        mm->cached_hole_size = ~0UL;
-       mm_init_cgroup(mm, p);
+       mm_init_owner(mm, p);
 
        if (likely(!mm_alloc_pgd(mm))) {
                mm->def_flags = 0;
                return mm;
        }
 
-       mm_free_cgroup(mm);
        free_mm(mm);
        return NULL;
 }
@@ -432,13 +431,13 @@ void mmput(struct mm_struct *mm)
        if (atomic_dec_and_test(&mm->mm_users)) {
                exit_aio(mm);
                exit_mmap(mm);
+               set_mm_exe_file(mm, NULL);
                if (!list_empty(&mm->mmlist)) {
                        spin_lock(&mmlist_lock);
                        list_del(&mm->mmlist);
                        spin_unlock(&mmlist_lock);
                }
                put_swap_token(mm);
-               mm_free_cgroup(mm);
                mmdrop(mm);
        }
 }
@@ -545,6 +544,8 @@ struct mm_struct *dup_mm(struct task_struct *tsk)
        if (init_new_context(tsk, mm))
                goto fail_nocontext;
 
+       dup_mm_exe_file(oldmm, mm);
+
        err = dup_mmap(mm, oldmm);
        if (err)
                goto free_pt;
@@ -891,7 +892,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
        sig->group_exit_code = 0;
        sig->group_exit_task = NULL;
        sig->group_stop_count = 0;
-       sig->curr_target = NULL;
+       sig->curr_target = tsk;
        init_sigpending(&sig->shared_pending);
        INIT_LIST_HEAD(&sig->posix_timers);
 
@@ -982,6 +983,13 @@ static void rt_mutex_init_task(struct task_struct *p)
 #endif
 }
 
+#ifdef CONFIG_MM_OWNER
+void mm_init_owner(struct mm_struct *mm, struct task_struct *p)
+{
+       mm->owner = p;
+}
+#endif /* CONFIG_MM_OWNER */
+
 /*
  * This creates a new process as a copy of the old one,
  * but does not actually start it yet.
@@ -1663,18 +1671,6 @@ static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp
        return 0;
 }
 
-/*
- * Unsharing of semundo for tasks created with CLONE_SYSVSEM is not
- * supported yet
- */
-static int unshare_semundo(unsigned long unshare_flags, struct sem_undo_list **new_ulistp)
-{
-       if (unshare_flags & CLONE_SYSVSEM)
-               return -EINVAL;
-
-       return 0;
-}
-
 /*
  * unshare allows a process to 'unshare' part of the process
  * context which was originally shared using clone.  copy_*
@@ -1690,8 +1686,8 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
        struct sighand_struct *new_sigh = NULL;
        struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL;
        struct files_struct *fd, *new_fd = NULL;
-       struct sem_undo_list *new_ulist = NULL;
        struct nsproxy *new_nsproxy = NULL;
+       int do_sysvsem = 0;
 
        check_unshare_flags(&unshare_flags);
 
@@ -1703,6 +1699,13 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
                                CLONE_NEWNET))
                goto bad_unshare_out;
 
+       /*
+        * CLONE_NEWIPC must also detach from the undolist: after switching
+        * to a new ipc namespace, the semaphore arrays from the old
+        * namespace are unreachable.
+        */
+       if (unshare_flags & (CLONE_NEWIPC|CLONE_SYSVSEM))
+               do_sysvsem = 1;
        if ((err = unshare_thread(unshare_flags)))
                goto bad_unshare_out;
        if ((err = unshare_fs(unshare_flags, &new_fs)))
@@ -1713,13 +1716,17 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
                goto bad_unshare_cleanup_sigh;
        if ((err = unshare_fd(unshare_flags, &new_fd)))
                goto bad_unshare_cleanup_vm;
-       if ((err = unshare_semundo(unshare_flags, &new_ulist)))
-               goto bad_unshare_cleanup_fd;
        if ((err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy,
                        new_fs)))
-               goto bad_unshare_cleanup_semundo;
+               goto bad_unshare_cleanup_fd;
 
-       if (new_fs ||  new_mm || new_fd || new_ulist || new_nsproxy) {
+       if (new_fs ||  new_mm || new_fd || do_sysvsem || new_nsproxy) {
+               if (do_sysvsem) {
+                       /*
+                        * CLONE_SYSVSEM is equivalent to sys_exit().
+                        */
+                       exit_sem(current);
+               }
 
                if (new_nsproxy) {
                        switch_task_namespaces(current, new_nsproxy);
@@ -1755,7 +1762,6 @@ asmlinkage long sys_unshare(unsigned long unshare_flags)
        if (new_nsproxy)
                put_nsproxy(new_nsproxy);
 
-bad_unshare_cleanup_semundo:
 bad_unshare_cleanup_fd:
        if (new_fd)
                put_files_struct(new_fd);
index e43945e995f54040aecc49678922b9e18186db52..98092c9817f42597c8c9a51b5ca1c4ce90509548 100644 (file)
@@ -1266,11 +1266,13 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
                if (!abs_time)
                        schedule();
                else {
-                       hrtimer_init(&t.timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+                       hrtimer_init_on_stack(&t.timer, CLOCK_MONOTONIC,
+                                               HRTIMER_MODE_ABS);
                        hrtimer_init_sleeper(&t, current);
                        t.timer.expires = *abs_time;
 
-                       hrtimer_start(&t.timer, t.timer.expires, HRTIMER_MODE_ABS);
+                       hrtimer_start(&t.timer, t.timer.expires,
+                                               HRTIMER_MODE_ABS);
                        if (!hrtimer_active(&t.timer))
                                t.task = NULL;
 
@@ -1286,6 +1288,8 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
 
                        /* Flag if a timeout occured */
                        rem = (t.task == NULL);
+
+                       destroy_hrtimer_on_stack(&t.timer);
                }
        }
        __set_current_state(TASK_RUNNING);
@@ -1367,7 +1371,8 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
 
        if (time) {
                to = &timeout;
-               hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
+               hrtimer_init_on_stack(&to->timer, CLOCK_REALTIME,
+                                     HRTIMER_MODE_ABS);
                hrtimer_init_sleeper(to, current);
                to->timer.expires = *time;
        }
@@ -1581,6 +1586,8 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
        unqueue_me_pi(&q);
        futex_unlock_mm(fshared);
 
+       if (to)
+               destroy_hrtimer_on_stack(&to->timer);
        return ret != -EINTR ? ret : -ERESTARTNOINTR;
 
  out_unlock_release_sem:
@@ -1588,6 +1595,8 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
 
  out_release_sem:
        futex_unlock_mm(fshared);
+       if (to)
+               destroy_hrtimer_on_stack(&to->timer);
        return ret;
 
  uaddr_faulted:
@@ -1615,6 +1624,8 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
        if (!ret && (uval != -EFAULT))
                goto retry;
 
+       if (to)
+               destroy_hrtimer_on_stack(&to->timer);
        return ret;
 }
 
index dea4c9124ac808b872d43a3dd83c15fc7cbb38a9..9af1d6a8095e40f80e64cdade6c0c3b505184466 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/tick.h>
 #include <linux/seq_file.h>
 #include <linux/err.h>
+#include <linux/debugobjects.h>
 
 #include <asm/uaccess.h>
 
@@ -342,6 +343,115 @@ ktime_t ktime_add_safe(const ktime_t lhs, const ktime_t rhs)
        return res;
 }
 
+#ifdef CONFIG_DEBUG_OBJECTS_TIMERS
+
+static struct debug_obj_descr hrtimer_debug_descr;
+
+/*
+ * fixup_init is called when:
+ * - an active object is initialized
+ */
+static int hrtimer_fixup_init(void *addr, enum debug_obj_state state)
+{
+       struct hrtimer *timer = addr;
+
+       switch (state) {
+       case ODEBUG_STATE_ACTIVE:
+               hrtimer_cancel(timer);
+               debug_object_init(timer, &hrtimer_debug_descr);
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+/*
+ * fixup_activate is called when:
+ * - an active object is activated
+ * - an unknown object is activated (might be a statically initialized object)
+ */
+static int hrtimer_fixup_activate(void *addr, enum debug_obj_state state)
+{
+       switch (state) {
+
+       case ODEBUG_STATE_NOTAVAILABLE:
+               WARN_ON_ONCE(1);
+               return 0;
+
+       case ODEBUG_STATE_ACTIVE:
+               WARN_ON(1);
+
+       default:
+               return 0;
+       }
+}
+
+/*
+ * fixup_free is called when:
+ * - an active object is freed
+ */
+static int hrtimer_fixup_free(void *addr, enum debug_obj_state state)
+{
+       struct hrtimer *timer = addr;
+
+       switch (state) {
+       case ODEBUG_STATE_ACTIVE:
+               hrtimer_cancel(timer);
+               debug_object_free(timer, &hrtimer_debug_descr);
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static struct debug_obj_descr hrtimer_debug_descr = {
+       .name           = "hrtimer",
+       .fixup_init     = hrtimer_fixup_init,
+       .fixup_activate = hrtimer_fixup_activate,
+       .fixup_free     = hrtimer_fixup_free,
+};
+
+static inline void debug_hrtimer_init(struct hrtimer *timer)
+{
+       debug_object_init(timer, &hrtimer_debug_descr);
+}
+
+static inline void debug_hrtimer_activate(struct hrtimer *timer)
+{
+       debug_object_activate(timer, &hrtimer_debug_descr);
+}
+
+static inline void debug_hrtimer_deactivate(struct hrtimer *timer)
+{
+       debug_object_deactivate(timer, &hrtimer_debug_descr);
+}
+
+static inline void debug_hrtimer_free(struct hrtimer *timer)
+{
+       debug_object_free(timer, &hrtimer_debug_descr);
+}
+
+static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
+                          enum hrtimer_mode mode);
+
+void hrtimer_init_on_stack(struct hrtimer *timer, clockid_t clock_id,
+                          enum hrtimer_mode mode)
+{
+       debug_object_init_on_stack(timer, &hrtimer_debug_descr);
+       __hrtimer_init(timer, clock_id, mode);
+}
+
+void destroy_hrtimer_on_stack(struct hrtimer *timer)
+{
+       debug_object_free(timer, &hrtimer_debug_descr);
+}
+
+#else
+static inline void debug_hrtimer_init(struct hrtimer *timer) { }
+static inline void debug_hrtimer_activate(struct hrtimer *timer) { }
+static inline void debug_hrtimer_deactivate(struct hrtimer *timer) { }
+#endif
+
 /*
  * Check, whether the timer is on the callback pending list
  */
@@ -567,6 +677,7 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
                /* Timer is expired, act upon the callback mode */
                switch(timer->cb_mode) {
                case HRTIMER_CB_IRQSAFE_NO_RESTART:
+                       debug_hrtimer_deactivate(timer);
                        /*
                         * We can call the callback from here. No restart
                         * happens, so no danger of recursion
@@ -581,6 +692,7 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
                         * the tick timer in the softirq ! The calling site
                         * takes care of this.
                         */
+                       debug_hrtimer_deactivate(timer);
                        return 1;
                case HRTIMER_CB_IRQSAFE:
                case HRTIMER_CB_SOFTIRQ:
@@ -735,6 +847,8 @@ static void enqueue_hrtimer(struct hrtimer *timer,
        struct hrtimer *entry;
        int leftmost = 1;
 
+       debug_hrtimer_activate(timer);
+
        /*
         * Find the right place in the rbtree:
         */
@@ -831,6 +945,7 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base)
                 * reprogramming happens in the interrupt handler. This is a
                 * rare case and less expensive than a smp call.
                 */
+               debug_hrtimer_deactivate(timer);
                timer_stats_hrtimer_clear_start_info(timer);
                reprogram = base->cpu_base == &__get_cpu_var(hrtimer_bases);
                __remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE,
@@ -878,6 +993,7 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
                tim = ktime_add_safe(tim, base->resolution);
 #endif
        }
+
        timer->expires = tim;
 
        timer_stats_hrtimer_set_start_info(timer);
@@ -1011,14 +1127,8 @@ ktime_t hrtimer_get_next_event(void)
 }
 #endif
 
-/**
- * hrtimer_init - initialize a timer to the given clock
- * @timer:     the timer to be initialized
- * @clock_id:  the clock to be used
- * @mode:      timer mode abs/rel
- */
-void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
-                 enum hrtimer_mode mode)
+static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
+                          enum hrtimer_mode mode)
 {
        struct hrtimer_cpu_base *cpu_base;
 
@@ -1039,6 +1149,19 @@ void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
        memset(timer->start_comm, 0, TASK_COMM_LEN);
 #endif
 }
+
+/**
+ * hrtimer_init - initialize a timer to the given clock
+ * @timer:     the timer to be initialized
+ * @clock_id:  the clock to be used
+ * @mode:      timer mode abs/rel
+ */
+void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
+                 enum hrtimer_mode mode)
+{
+       debug_hrtimer_init(timer);
+       __hrtimer_init(timer, clock_id, mode);
+}
 EXPORT_SYMBOL_GPL(hrtimer_init);
 
 /**
@@ -1072,6 +1195,7 @@ static void run_hrtimer_pending(struct hrtimer_cpu_base *cpu_base)
                timer = list_entry(cpu_base->cb_pending.next,
                                   struct hrtimer, cb_entry);
 
+               debug_hrtimer_deactivate(timer);
                timer_stats_account_hrtimer(timer);
 
                fn = timer->function;
@@ -1120,6 +1244,7 @@ static void __run_hrtimer(struct hrtimer *timer)
        enum hrtimer_restart (*fn)(struct hrtimer *);
        int restart;
 
+       debug_hrtimer_deactivate(timer);
        __remove_hrtimer(timer, base, HRTIMER_STATE_CALLBACK, 0);
        timer_stats_account_hrtimer(timer);
 
@@ -1378,22 +1503,27 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
 {
        struct hrtimer_sleeper t;
        struct timespec __user  *rmtp;
+       int ret = 0;
 
-       hrtimer_init(&t.timer, restart->nanosleep.index, HRTIMER_MODE_ABS);
+       hrtimer_init_on_stack(&t.timer, restart->nanosleep.index,
+                               HRTIMER_MODE_ABS);
        t.timer.expires.tv64 = restart->nanosleep.expires;
 
        if (do_nanosleep(&t, HRTIMER_MODE_ABS))
-               return 0;
+               goto out;
 
        rmtp = restart->nanosleep.rmtp;
        if (rmtp) {
-               int ret = update_rmtp(&t.timer, rmtp);
+               ret = update_rmtp(&t.timer, rmtp);
                if (ret <= 0)
-                       return ret;
+                       goto out;
        }
 
        /* The other values in restart are already filled in */
-       return -ERESTART_RESTARTBLOCK;
+       ret = -ERESTART_RESTARTBLOCK;
+out:
+       destroy_hrtimer_on_stack(&t.timer);
+       return ret;
 }
 
 long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
@@ -1401,20 +1531,23 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
 {
        struct restart_block *restart;
        struct hrtimer_sleeper t;
+       int ret = 0;
 
-       hrtimer_init(&t.timer, clockid, mode);
+       hrtimer_init_on_stack(&t.timer, clockid, mode);
        t.timer.expires = timespec_to_ktime(*rqtp);
        if (do_nanosleep(&t, mode))
-               return 0;
+               goto out;
 
        /* Absolute timers do not update the rmtp value and restart: */
-       if (mode == HRTIMER_MODE_ABS)
-               return -ERESTARTNOHAND;
+       if (mode == HRTIMER_MODE_ABS) {
+               ret = -ERESTARTNOHAND;
+               goto out;
+       }
 
        if (rmtp) {
-               int ret = update_rmtp(&t.timer, rmtp);
+               ret = update_rmtp(&t.timer, rmtp);
                if (ret <= 0)
-                       return ret;
+                       goto out;
        }
 
        restart = &current_thread_info()->restart_block;
@@ -1423,7 +1556,10 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
        restart->nanosleep.rmtp = rmtp;
        restart->nanosleep.expires = t.timer.expires.tv64;
 
-       return -ERESTART_RESTARTBLOCK;
+       ret = -ERESTART_RESTARTBLOCK;
+out:
+       destroy_hrtimer_on_stack(&t.timer);
+       return ret;
 }
 
 asmlinkage long
@@ -1468,6 +1604,7 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base,
        while ((node = rb_first(&old_base->active))) {
                timer = rb_entry(node, struct hrtimer, node);
                BUG_ON(hrtimer_callback_running(timer));
+               debug_hrtimer_deactivate(timer);
                __remove_hrtimer(timer, old_base, HRTIMER_STATE_INACTIVE, 0);
                timer->base = new_base;
                /*
index 6d9204f3a370cfa30b35c9712e15dd5c8723d49c..38a25b8d8bff6d15448270d4f56983537335fc2d 100644 (file)
@@ -1,6 +1,7 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
+#include <linux/gfp.h>
 
 /*
  * Device resource management aware IRQ request/free implementation.
index 438a01464287fc391b8da015fbe7c80a666c4928..46e4ad1723f0545377c342c57a988a5ff99fef9c 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/random.h>
 #include <linux/interrupt.h>
+#include <linux/slab.h>
 
 #include "internals.h"
 
index f091d13def0083b8d25107993affa1065cb8aabc..6fc0040f3e3abacade62c7d63f74d240974d80fe 100644 (file)
@@ -472,11 +472,7 @@ static const struct file_operations kallsyms_operations = {
 
 static int __init kallsyms_init(void)
 {
-       struct proc_dir_entry *entry;
-
-       entry = create_proc_entry("kallsyms", 0444, NULL);
-       if (entry)
-               entry->proc_fops = &kallsyms_operations;
+       proc_create("kallsyms", 0444, NULL, &kallsyms_operations);
        return 0;
 }
 __initcall(kallsyms_init);
index 92cf6930ab51a74e034ae9db30d72b21e9a84e9d..bd1b9ea024e1238cb230c159c426f3a4f0c8981e 100644 (file)
@@ -98,7 +98,7 @@ static void create_kthread(struct kthread_create_info *create)
                struct sched_param param = { .sched_priority = 0 };
                wait_for_completion(&create->started);
                read_lock(&tasklist_lock);
-               create->result = find_task_by_pid(pid);
+               create->result = find_task_by_pid_ns(pid, &init_pid_ns);
                read_unlock(&tasklist_lock);
                /*
                 * root may have changed our (kthreadd's) priority or CPU mask.
@@ -144,9 +144,9 @@ struct task_struct *kthread_create(int (*threadfn)(void *data),
 
        spin_lock(&kthread_create_lock);
        list_add_tail(&create.list, &kthread_create_list);
-       wake_up_process(kthreadd_task);
        spin_unlock(&kthread_create_lock);
 
+       wake_up_process(kthreadd_task);
        wait_for_completion(&create.done);
 
        if (!IS_ERR(create.result)) {
index 7c74dab0d21b9fcd2235b507b5e450459e042ef6..5e7b45c569233536ef23dadfafd90e40d20b7f62 100644 (file)
@@ -233,14 +233,7 @@ static struct file_operations lstats_fops = {
 
 static int __init init_lstats_procfs(void)
 {
-       struct proc_dir_entry *pe;
-
-       pe = create_proc_entry("latency_stats", 0644, NULL);
-       if (!pe)
-               return -ENOMEM;
-
-       pe->proc_fops = &lstats_fops;
-
+       proc_create("latency_stats", 0644, NULL, &lstats_fops);
        return 0;
 }
 __initcall(init_lstats_procfs);
index 8a135bd163c2cc719b4635b1e511aa87039d6f46..dc5d29648d852ccadd88ea79a91decc93653fa8b 100644 (file)
@@ -660,20 +660,12 @@ static const struct file_operations proc_lock_stat_operations = {
 
 static int __init lockdep_proc_init(void)
 {
-       struct proc_dir_entry *entry;
-
-       entry = create_proc_entry("lockdep", S_IRUSR, NULL);
-       if (entry)
-               entry->proc_fops = &proc_lockdep_operations;
-
-       entry = create_proc_entry("lockdep_stats", S_IRUSR, NULL);
-       if (entry)
-               entry->proc_fops = &proc_lockdep_stats_operations;
+       proc_create("lockdep", S_IRUSR, NULL, &proc_lockdep_operations);
+       proc_create("lockdep_stats", S_IRUSR, NULL,
+                   &proc_lockdep_stats_operations);
 
 #ifdef CONFIG_LOCK_STAT
-       entry = create_proc_entry("lock_stat", S_IRUSR, NULL);
-       if (entry)
-               entry->proc_fops = &proc_lock_stat_operations;
+       proc_create("lock_stat", S_IRUSR, NULL, &proc_lock_stat_operations);
 #endif
 
        return 0;
index 005b959545933703bbb76e3f9720c5e42466df99..b5a9fe1d50d5ce1c480ca7ca1777e55e6deb485e 100644 (file)
 #include <linux/rcupdate.h>
 #include <linux/marker.h>
 #include <linux/err.h>
+#include <linux/slab.h>
 
 extern struct marker __start___markers[];
 extern struct marker __stop___markers[];
 
 /* Set to 1 to enable marker debug output */
-const int marker_debug;
+static const int marker_debug;
 
 /*
  * markers_mutex nests inside module_mutex. Markers mutex protects the builtin
index 643360d1bb144fda223301b348059cd5381eb35e..823be11584efef8ef1d344f484cbf8c3d4f9617e 100644 (file)
@@ -31,6 +31,21 @@ static int notifier_chain_register(struct notifier_block **nl,
        return 0;
 }
 
+static int notifier_chain_cond_register(struct notifier_block **nl,
+               struct notifier_block *n)
+{
+       while ((*nl) != NULL) {
+               if ((*nl) == n)
+                       return 0;
+               if (n->priority > (*nl)->priority)
+                       break;
+               nl = &((*nl)->next);
+       }
+       n->next = *nl;
+       rcu_assign_pointer(*nl, n);
+       return 0;
+}
+
 static int notifier_chain_unregister(struct notifier_block **nl,
                struct notifier_block *n)
 {
@@ -204,6 +219,29 @@ int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
 }
 EXPORT_SYMBOL_GPL(blocking_notifier_chain_register);
 
+/**
+ *     blocking_notifier_chain_cond_register - Cond add notifier to a blocking notifier chain
+ *     @nh: Pointer to head of the blocking notifier chain
+ *     @n: New entry in notifier chain
+ *
+ *     Adds a notifier to a blocking notifier chain, only if not already
+ *     present in the chain.
+ *     Must be called in process context.
+ *
+ *     Currently always returns zero.
+ */
+int blocking_notifier_chain_cond_register(struct blocking_notifier_head *nh,
+               struct notifier_block *n)
+{
+       int ret;
+
+       down_write(&nh->rwsem);
+       ret = notifier_chain_cond_register(&nh->head, n);
+       up_write(&nh->rwsem);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(blocking_notifier_chain_cond_register);
+
 /**
  *     blocking_notifier_chain_unregister - Remove notifier from a blocking notifier chain
  *     @nh: Pointer to head of the blocking notifier chain
index aead4d69f62b80f0cf648eb8213bc633caf6d8de..48d7ed6fc3a4d2dcc206d5eb304f55ae7436ac70 100644 (file)
@@ -7,6 +7,8 @@
 #include <linux/module.h>
 #include <linux/cgroup.h>
 #include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/nsproxy.h>
 
 struct ns_cgroup {
        struct cgroup_subsys_state css;
index f5d332cf8c631704b1ee440c35317644e4f6eff9..adc785146a1cb81d6f7b3d676877921f10bb59e7 100644 (file)
@@ -139,6 +139,18 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
                goto out;
        }
 
+       /*
+        * CLONE_NEWIPC must detach from the undolist: after switching
+        * to a new ipc namespace, the semaphore arrays from the old
+        * namespace are unreachable.  In clone parlance, CLONE_SYSVSEM
+        * means share undolist with parent, so we must forbid using
+        * it along with CLONE_NEWIPC.
+        */
+       if ((flags & CLONE_NEWIPC) && (flags & CLONE_SYSVSEM)) {
+               err = -EINVAL;
+               goto out;
+       }
+
        new_ns = create_new_namespaces(flags, tsk, tsk->fs);
        if (IS_ERR(new_ns)) {
                err = PTR_ERR(new_ns);
index 24af9f8bac99204076ab80b36038d1d5404ae27a..425567f45b9f776148f1767b2f4af2d357a0c2fd 100644 (file)
@@ -153,6 +153,8 @@ EXPORT_SYMBOL(panic);
  *  'M' - System experienced a machine check exception.
  *  'B' - System has hit bad_page.
  *  'U' - Userspace-defined naughtiness.
+ *  'A' - ACPI table overridden.
+ *  'W' - Taint on warning.
  *
  *     The string is overwritten by the next call to print_taint().
  */
@@ -161,7 +163,7 @@ const char *print_tainted(void)
 {
        static char buf[20];
        if (tainted) {
-               snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c%c%c",
+               snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c%c%c%c",
                        tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G',
                        tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
                        tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
@@ -170,7 +172,8 @@ const char *print_tainted(void)
                        tainted & TAINT_BAD_PAGE ? 'B' : ' ',
                        tainted & TAINT_USER ? 'U' : ' ',
                        tainted & TAINT_DIE ? 'D' : ' ',
-                       tainted & TAINT_OVERRIDDEN_ACPI_TABLE ? 'A' : ' ');
+                       tainted & TAINT_OVERRIDDEN_ACPI_TABLE ? 'A' : ' ',
+                       tainted & TAINT_WARN ? 'W' : ' ');
        }
        else
                snprintf(buf, sizeof(buf), "Not tainted");
@@ -312,6 +315,7 @@ void warn_on_slowpath(const char *file, int line)
        print_modules();
        dump_stack();
        print_oops_end_marker();
+       add_taint(TAINT_WARN);
 }
 EXPORT_SYMBOL(warn_on_slowpath);
 #endif
index 477691576b338b38caa173c386b3a70ce7351a72..20d59fa2d493c7a20b83ff151745e38a847e0366 100644 (file)
@@ -111,10 +111,11 @@ EXPORT_SYMBOL(is_container_init);
 
 static  __cacheline_aligned_in_smp DEFINE_SPINLOCK(pidmap_lock);
 
-static void free_pidmap(struct pid_namespace *pid_ns, int pid)
+static void free_pidmap(struct upid *upid)
 {
-       struct pidmap *map = pid_ns->pidmap + pid / BITS_PER_PAGE;
-       int offset = pid & BITS_PER_PAGE_MASK;
+       int nr = upid->nr;
+       struct pidmap *map = upid->ns->pidmap + nr / BITS_PER_PAGE;
+       int offset = nr & BITS_PER_PAGE_MASK;
 
        clear_bit(offset, map->page);
        atomic_inc(&map->nr_free);
@@ -232,7 +233,7 @@ void free_pid(struct pid *pid)
        spin_unlock_irqrestore(&pidmap_lock, flags);
 
        for (i = 0; i <= pid->level; i++)
-               free_pidmap(pid->numbers[i].ns, pid->numbers[i].nr);
+               free_pidmap(pid->numbers + i);
 
        call_rcu(&pid->rcu, delayed_put_pid);
 }
@@ -278,8 +279,8 @@ out:
        return pid;
 
 out_free:
-       for (i++; i <= ns->level; i++)
-               free_pidmap(pid->numbers[i].ns, pid->numbers[i].nr);
+       while (++i <= ns->level)
+               free_pidmap(pid->numbers + i);
 
        kmem_cache_free(ns->pid_cachep, pid);
        pid = NULL;
@@ -316,7 +317,7 @@ EXPORT_SYMBOL_GPL(find_pid);
 /*
  * attach_pid() must be called with the tasklist_lock write-held.
  */
-int attach_pid(struct task_struct *task, enum pid_type type,
+void attach_pid(struct task_struct *task, enum pid_type type,
                struct pid *pid)
 {
        struct pid_link *link;
@@ -324,11 +325,10 @@ int attach_pid(struct task_struct *task, enum pid_type type,
        link = &task->pids[type];
        link->pid = pid;
        hlist_add_head_rcu(&link->node, &pid->tasks[type]);
-
-       return 0;
 }
 
-void detach_pid(struct task_struct *task, enum pid_type type)
+static void __change_pid(struct task_struct *task, enum pid_type type,
+                       struct pid *new)
 {
        struct pid_link *link;
        struct pid *pid;
@@ -338,7 +338,7 @@ void detach_pid(struct task_struct *task, enum pid_type type)
        pid = link->pid;
 
        hlist_del_rcu(&link->node);
-       link->pid = NULL;
+       link->pid = new;
 
        for (tmp = PIDTYPE_MAX; --tmp >= 0; )
                if (!hlist_empty(&pid->tasks[tmp]))
@@ -347,13 +347,24 @@ void detach_pid(struct task_struct *task, enum pid_type type)
        free_pid(pid);
 }
 
+void detach_pid(struct task_struct *task, enum pid_type type)
+{
+       __change_pid(task, type, NULL);
+}
+
+void change_pid(struct task_struct *task, enum pid_type type,
+               struct pid *pid)
+{
+       __change_pid(task, type, pid);
+       attach_pid(task, type, pid);
+}
+
 /* transfer_pid is an optimization of attach_pid(new), detach_pid(old) */
 void transfer_pid(struct task_struct *old, struct task_struct *new,
                           enum pid_type type)
 {
        new->pids[type].pid = old->pids[type].pid;
        hlist_replace_rcu(&old->pids[type].node, &new->pids[type].node);
-       old->pids[type].pid = NULL;
 }
 
 struct task_struct *pid_task(struct pid *pid, enum pid_type type)
@@ -380,12 +391,6 @@ struct task_struct *find_task_by_pid_type_ns(int type, int nr,
 
 EXPORT_SYMBOL(find_task_by_pid_type_ns);
 
-struct task_struct *find_task_by_pid(pid_t nr)
-{
-       return find_task_by_pid_type_ns(PIDTYPE_PID, nr, &init_pid_ns);
-}
-EXPORT_SYMBOL(find_task_by_pid);
-
 struct task_struct *find_task_by_vpid(pid_t vnr)
 {
        return find_task_by_pid_type_ns(PIDTYPE_PID, vnr,
index 5ca37fa50beb5b4d66b79e9c596943c80d363dfc..98702b4b8851762969d9ddad76505e5739e8166c 100644 (file)
@@ -66,7 +66,7 @@ err_alloc:
        return NULL;
 }
 
-static struct pid_namespace *create_pid_namespace(int level)
+static struct pid_namespace *create_pid_namespace(unsigned int level)
 {
        struct pid_namespace *ns;
        int i;
index 8476956ffd9238a378f6c5671649900776939dd0..dbd8398ddb0b41fa1f391849b82199078e72de70 100644 (file)
@@ -310,8 +310,7 @@ int posix_timer_event(struct k_itimer *timr,int si_private)
 
        if (timr->it_sigev_notify & SIGEV_THREAD_ID) {
                struct task_struct *leader;
-               int ret = send_sigqueue(timr->it_sigev_signo, timr->sigq,
-                                       timr->it_process);
+               int ret = send_sigqueue(timr->sigq, timr->it_process, 0);
 
                if (likely(ret >= 0))
                        return ret;
@@ -322,8 +321,7 @@ int posix_timer_event(struct k_itimer *timr,int si_private)
                timr->it_process = leader;
        }
 
-       return send_group_sigqueue(timr->it_sigev_signo, timr->sigq,
-                                  timr->it_process);
+       return send_sigqueue(timr->sigq, timr->it_process, 1);
 }
 EXPORT_SYMBOL_GPL(posix_timer_event);
 
index bdd4ea8c3f2b67520c1a55e0ba34a0a247d350fc..8fb01c32aa3bb7eaf44f5b9e63e316628dd935c1 100644 (file)
@@ -111,6 +111,9 @@ struct console_cmdline
        char    name[8];                        /* Name of the driver       */
        int     index;                          /* Minor dev. to use        */
        char    *options;                       /* Options for the driver   */
+#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
+       char    *brl_options;                   /* Options for braille driver */
+#endif
 };
 
 #define MAX_CMDLINECONSOLES 8
@@ -808,15 +811,60 @@ static void call_console_drivers(unsigned start, unsigned end)
 
 #endif
 
+static int __add_preferred_console(char *name, int idx, char *options,
+                                  char *brl_options)
+{
+       struct console_cmdline *c;
+       int i;
+
+       /*
+        *      See if this tty is not yet registered, and
+        *      if we have a slot free.
+        */
+       for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
+               if (strcmp(console_cmdline[i].name, name) == 0 &&
+                         console_cmdline[i].index == idx) {
+                               if (!brl_options)
+                                       selected_console = i;
+                               return 0;
+               }
+       if (i == MAX_CMDLINECONSOLES)
+               return -E2BIG;
+       if (!brl_options)
+               selected_console = i;
+       c = &console_cmdline[i];
+       strlcpy(c->name, name, sizeof(c->name));
+       c->options = options;
+#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
+       c->brl_options = brl_options;
+#endif
+       c->index = idx;
+       return 0;
+}
 /*
  * Set up a list of consoles.  Called from init/main.c
  */
 static int __init console_setup(char *str)
 {
        char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for index */
-       char *s, *options;
+       char *s, *options, *brl_options = NULL;
        int idx;
 
+#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
+       if (!memcmp(str, "brl,", 4)) {
+               brl_options = "";
+               str += 4;
+       } else if (!memcmp(str, "brl=", 4)) {
+               brl_options = str + 4;
+               str = strchr(brl_options, ',');
+               if (!str) {
+                       printk(KERN_ERR "need port name after brl=\n");
+                       return 1;
+               }
+               *(str++) = 0;
+       }
+#endif
+
        /*
         * Decode str into name, index, options.
         */
@@ -841,7 +889,7 @@ static int __init console_setup(char *str)
        idx = simple_strtoul(s, NULL, 10);
        *s = 0;
 
-       add_preferred_console(buf, idx, options);
+       __add_preferred_console(buf, idx, options, brl_options);
        return 1;
 }
 __setup("console=", console_setup);
@@ -861,28 +909,7 @@ __setup("console=", console_setup);
  */
 int add_preferred_console(char *name, int idx, char *options)
 {
-       struct console_cmdline *c;
-       int i;
-
-       /*
-        *      See if this tty is not yet registered, and
-        *      if we have a slot free.
-        */
-       for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
-               if (strcmp(console_cmdline[i].name, name) == 0 &&
-                         console_cmdline[i].index == idx) {
-                               selected_console = i;
-                               return 0;
-               }
-       if (i == MAX_CMDLINECONSOLES)
-               return -E2BIG;
-       selected_console = i;
-       c = &console_cmdline[i];
-       memcpy(c->name, name, sizeof(c->name));
-       c->name[sizeof(c->name) - 1] = 0;
-       c->options = options;
-       c->index = idx;
-       return 0;
+       return __add_preferred_console(name, idx, options, NULL);
 }
 
 int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options)
@@ -894,7 +921,7 @@ int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, cha
                if (strcmp(console_cmdline[i].name, name) == 0 &&
                          console_cmdline[i].index == idx) {
                                c = &console_cmdline[i];
-                               memcpy(c->name, name_new, sizeof(c->name));
+                               strlcpy(c->name, name_new, sizeof(c->name));
                                c->name[sizeof(c->name) - 1] = 0;
                                c->options = options;
                                c->index = idx_new;
@@ -1163,6 +1190,16 @@ void register_console(struct console *console)
                        continue;
                if (console->index < 0)
                        console->index = console_cmdline[i].index;
+#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
+               if (console_cmdline[i].brl_options) {
+                       console->flags |= CON_BRL;
+                       braille_register_console(console,
+                                       console_cmdline[i].index,
+                                       console_cmdline[i].options,
+                                       console_cmdline[i].brl_options);
+                       return;
+               }
+#endif
                if (console->setup &&
                    console->setup(console, console_cmdline[i].options) != 0)
                        break;
@@ -1221,6 +1258,11 @@ int unregister_console(struct console *console)
         struct console *a, *b;
        int res = 1;
 
+#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
+       if (console->flags & CON_BRL)
+               return braille_unregister_console(console);
+#endif
+
        acquire_console_sem();
        if (console_drivers == console) {
                console_drivers=console->next;
@@ -1272,8 +1314,8 @@ late_initcall(disable_boot_consoles);
  */
 void tty_write_message(struct tty_struct *tty, char *msg)
 {
-       if (tty && tty->driver->write)
-               tty->driver->write(tty, msg, strlen(msg));
+       if (tty && tty->ops->write)
+               tty->ops->write(tty, msg, strlen(msg));
        return;
 }
 
@@ -1287,31 +1329,7 @@ void tty_write_message(struct tty_struct *tty, char *msg)
  */
 int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst)
 {
-       static DEFINE_SPINLOCK(ratelimit_lock);
-       static unsigned toks = 10 * 5 * HZ;
-       static unsigned long last_msg;
-       static int missed;
-       unsigned long flags;
-       unsigned long now = jiffies;
-
-       spin_lock_irqsave(&ratelimit_lock, flags);
-       toks += now - last_msg;
-       last_msg = now;
-       if (toks > (ratelimit_burst * ratelimit_jiffies))
-               toks = ratelimit_burst * ratelimit_jiffies;
-       if (toks >= ratelimit_jiffies) {
-               int lost = missed;
-
-               missed = 0;
-               toks -= ratelimit_jiffies;
-               spin_unlock_irqrestore(&ratelimit_lock, flags);
-               if (lost)
-                       printk(KERN_WARNING "printk: %d messages suppressed.\n", lost);
-               return 1;
-       }
-       missed++;
-       spin_unlock_irqrestore(&ratelimit_lock, flags);
-       return 0;
+       return __ratelimit(ratelimit_jiffies, ratelimit_burst);
 }
 EXPORT_SYMBOL(__printk_ratelimit);
 
index 606d7387265ccee0c030c0afdf317ede0d943f26..ae7ead82cbc9f7bd25a15ec373c14a1f2ea79bf5 100644 (file)
@@ -587,10 +587,10 @@ static int __init create_proc_profile(void)
                return 0;
        if (create_hash_tables())
                return -1;
-       entry = create_proc_entry("profile", S_IWUSR | S_IRUGO, NULL);
+       entry = proc_create("profile", S_IWUSR | S_IRUGO,
+                           NULL, &proc_profile_operations);
        if (!entry)
                return 0;
-       entry->proc_fops = &proc_profile_operations;
        entry->size = (1+prof_len) * sizeof(atomic_t);
        hotcpu_notifier(profile_cpu_callback, 0);
        return 0;
index dac4b4e572931b5cd7fd7da192883e3ad2febf0b..dcc199c43a12abcb9e62b4a70e090084d3075fa4 100644 (file)
@@ -73,7 +73,7 @@ void __ptrace_unlink(struct task_struct *child)
        BUG_ON(!child->ptrace);
 
        child->ptrace = 0;
-       if (!list_empty(&child->ptrace_list)) {
+       if (ptrace_reparented(child)) {
                list_del_init(&child->ptrace_list);
                remove_parent(child);
                child->parent = child->real_parent;
@@ -168,8 +168,6 @@ int ptrace_attach(struct task_struct *task)
        audit_ptrace(task);
 
        retval = -EPERM;
-       if (task->pid <= 1)
-               goto out;
        if (same_thread_group(task, current))
                goto out;
 
@@ -208,8 +206,7 @@ repeat:
 
        __ptrace_link(task, current);
 
-       force_sig_specific(SIGSTOP, task);
-
+       send_sig_info(SIGSTOP, SEND_SIG_FORCED, task);
 bad:
        write_unlock_irqrestore(&tasklist_lock, flags);
        task_unlock(task);
@@ -522,12 +519,6 @@ struct task_struct *ptrace_get_task_struct(pid_t pid)
 {
        struct task_struct *child;
 
-       /*
-        * Tracing init is not allowed.
-        */
-       if (pid == 1)
-               return ERR_PTR(-EPERM);
-
        read_lock(&tasklist_lock);
        child = find_task_by_vpid(pid);
        if (child)
index 47894f919d4ea2848263a3e1a5ec5218f27237e3..33acc424667e03381597d76771fa12c9ad777124 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/byteorder/swabb.h>
 #include <linux/stat.h>
 #include <linux/srcu.h>
+#include <linux/slab.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com> and "
index d6204a4858183c754d5d401ad230c11f60a546c1..7de644cdec43590be390d3037206e5722aa46856 100644 (file)
@@ -65,6 +65,35 @@ static struct vm_operations_struct relay_file_mmap_ops = {
        .close = relay_file_mmap_close,
 };
 
+/*
+ * allocate an array of pointers of struct page
+ */
+static struct page **relay_alloc_page_array(unsigned int n_pages)
+{
+       struct page **array;
+       size_t pa_size = n_pages * sizeof(struct page *);
+
+       if (pa_size > PAGE_SIZE) {
+               array = vmalloc(pa_size);
+               if (array)
+                       memset(array, 0, pa_size);
+       } else {
+               array = kzalloc(pa_size, GFP_KERNEL);
+       }
+       return array;
+}
+
+/*
+ * free an array of pointers of struct page
+ */
+static void relay_free_page_array(struct page **array)
+{
+       if (is_vmalloc_addr(array))
+               vfree(array);
+       else
+               kfree(array);
+}
+
 /**
  *     relay_mmap_buf: - mmap channel buffer to process address space
  *     @buf: relay channel buffer
@@ -109,7 +138,7 @@ static void *relay_alloc_buf(struct rchan_buf *buf, size_t *size)
        *size = PAGE_ALIGN(*size);
        n_pages = *size >> PAGE_SHIFT;
 
-       buf->page_array = kcalloc(n_pages, sizeof(struct page *), GFP_KERNEL);
+       buf->page_array = relay_alloc_page_array(n_pages);
        if (!buf->page_array)
                return NULL;
 
@@ -130,7 +159,7 @@ static void *relay_alloc_buf(struct rchan_buf *buf, size_t *size)
 depopulate:
        for (j = 0; j < i; j++)
                __free_page(buf->page_array[j]);
-       kfree(buf->page_array);
+       relay_free_page_array(buf->page_array);
        return NULL;
 }
 
@@ -189,7 +218,7 @@ static void relay_destroy_buf(struct rchan_buf *buf)
                vunmap(buf->start);
                for (i = 0; i < buf->page_count; i++)
                        __free_page(buf->page_array[i]);
-               kfree(buf->page_array);
+               relay_free_page_array(buf->page_array);
        }
        chan->buf[buf->cpu] = NULL;
        kfree(buf->padding);
@@ -1162,7 +1191,7 @@ static ssize_t relay_file_splice_read(struct file *in,
        ret = 0;
        spliced = 0;
 
-       while (len) {
+       while (len && !spliced) {
                ret = subbuf_splice_actor(in, ppos, pipe, len, flags, &nonpad_ret);
                if (ret < 0)
                        break;
index efbfc0fc232f33c49b5b918704b4e13ae5d0f2cc..d3c61b4ebef238c110ae3994e0d0fdc078fabfc8 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/types.h>
 #include <linux/parser.h>
 #include <linux/fs.h>
+#include <linux/slab.h>
 #include <linux/res_counter.h>
 #include <linux/uaccess.h>
 
@@ -27,6 +28,8 @@ int res_counter_charge_locked(struct res_counter *counter, unsigned long val)
        }
 
        counter->usage += val;
+       if (counter->usage > counter->max_usage)
+               counter->max_usage = counter->usage;
        return 0;
 }
 
@@ -65,6 +68,8 @@ res_counter_member(struct res_counter *counter, int member)
        switch (member) {
        case RES_USAGE:
                return &counter->usage;
+       case RES_MAX_USAGE:
+               return &counter->max_usage;
        case RES_LIMIT:
                return &counter->limit;
        case RES_FAILCNT:
@@ -92,6 +97,11 @@ ssize_t res_counter_read(struct res_counter *counter, int member,
                        pos, buf, s - buf);
 }
 
+u64 res_counter_read_u64(struct res_counter *counter, int member)
+{
+       return *res_counter_member(counter, member);
+}
+
 ssize_t res_counter_write(struct res_counter *counter, int member,
                const char __user *userbuf, size_t nbytes, loff_t *pos,
                int (*write_strategy)(char *st_buf, unsigned long long *val))
index cee12cc47cab04c270e9193341ba43e8c57fd92b..74af2d7cb5a135ffa1da4c52ce9af026c527044d 100644 (file)
@@ -131,14 +131,8 @@ static const struct file_operations proc_iomem_operations = {
 
 static int __init ioresources_init(void)
 {
-       struct proc_dir_entry *entry;
-
-       entry = create_proc_entry("ioports", 0, NULL);
-       if (entry)
-               entry->proc_fops = &proc_ioports_operations;
-       entry = create_proc_entry("iomem", 0, NULL);
-       if (entry)
-               entry->proc_fops = &proc_iomem_operations;
+       proc_create("ioports", 0, NULL, &proc_ioports_operations);
+       proc_create("iomem", 0, NULL, &proc_iomem_operations);
        return 0;
 }
 __initcall(ioresources_init);
index 740fb409e5bb32854dc9cc9b753cb25d83cdb7d4..e2f7f5acc80778328a892961d8e26faa7c4c8841 100644 (file)
@@ -9057,13 +9057,13 @@ cpu_cgroup_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
 }
 
 #ifdef CONFIG_FAIR_GROUP_SCHED
-static int cpu_shares_write_uint(struct cgroup *cgrp, struct cftype *cftype,
+static int cpu_shares_write_u64(struct cgroup *cgrp, struct cftype *cftype,
                                u64 shareval)
 {
        return sched_group_set_shares(cgroup_tg(cgrp), shareval);
 }
 
-static u64 cpu_shares_read_uint(struct cgroup *cgrp, struct cftype *cft)
+static u64 cpu_shares_read_u64(struct cgroup *cgrp, struct cftype *cft)
 {
        struct task_group *tg = cgroup_tg(cgrp);
 
@@ -9073,48 +9073,14 @@ static u64 cpu_shares_read_uint(struct cgroup *cgrp, struct cftype *cft)
 
 #ifdef CONFIG_RT_GROUP_SCHED
 static ssize_t cpu_rt_runtime_write(struct cgroup *cgrp, struct cftype *cft,
-                               struct file *file,
-                               const char __user *userbuf,
-                               size_t nbytes, loff_t *unused_ppos)
+                               s64 val)
 {
-       char buffer[64];
-       int retval = 0;
-       s64 val;
-       char *end;
-
-       if (!nbytes)
-               return -EINVAL;
-       if (nbytes >= sizeof(buffer))
-               return -E2BIG;
-       if (copy_from_user(buffer, userbuf, nbytes))
-               return -EFAULT;
-
-       buffer[nbytes] = 0;     /* nul-terminate */
-
-       /* strip newline if necessary */
-       if (nbytes && (buffer[nbytes-1] == '\n'))
-               buffer[nbytes-1] = 0;
-       val = simple_strtoll(buffer, &end, 0);
-       if (*end)
-               return -EINVAL;
-
-       /* Pass to subsystem */
-       retval = sched_group_set_rt_runtime(cgroup_tg(cgrp), val);
-       if (!retval)
-               retval = nbytes;
-       return retval;
+       return sched_group_set_rt_runtime(cgroup_tg(cgrp), val);
 }
 
-static ssize_t cpu_rt_runtime_read(struct cgroup *cgrp, struct cftype *cft,
-                                  struct file *file,
-                                  char __user *buf, size_t nbytes,
-                                  loff_t *ppos)
+static s64 cpu_rt_runtime_read(struct cgroup *cgrp, struct cftype *cft)
 {
-       char tmp[64];
-       long val = sched_group_rt_runtime(cgroup_tg(cgrp));
-       int len = sprintf(tmp, "%ld\n", val);
-
-       return simple_read_from_buffer(buf, nbytes, ppos, tmp, len);
+       return sched_group_rt_runtime(cgroup_tg(cgrp));
 }
 
 static int cpu_rt_period_write_uint(struct cgroup *cgrp, struct cftype *cftype,
@@ -9133,20 +9099,20 @@ static struct cftype cpu_files[] = {
 #ifdef CONFIG_FAIR_GROUP_SCHED
        {
                .name = "shares",
-               .read_uint = cpu_shares_read_uint,
-               .write_uint = cpu_shares_write_uint,
+               .read_u64 = cpu_shares_read_u64,
+               .write_u64 = cpu_shares_write_u64,
        },
 #endif
 #ifdef CONFIG_RT_GROUP_SCHED
        {
                .name = "rt_runtime_us",
-               .read = cpu_rt_runtime_read,
-               .write = cpu_rt_runtime_write,
+               .read_s64 = cpu_rt_runtime_read,
+               .write_s64 = cpu_rt_runtime_write,
        },
        {
                .name = "rt_period_us",
-               .read_uint = cpu_rt_period_read_uint,
-               .write_uint = cpu_rt_period_write_uint,
+               .read_u64 = cpu_rt_period_read_uint,
+               .write_u64 = cpu_rt_period_write_uint,
        },
 #endif
 };
@@ -9277,8 +9243,8 @@ out:
 static struct cftype files[] = {
        {
                .name = "usage",
-               .read_uint = cpuusage_read,
-               .write_uint = cpuusage_write,
+               .read_u64 = cpuusage_read,
+               .write_u64 = cpuusage_write,
        },
 };
 
index f3f4af4b8b0fb8ffa4e24da75f5982358c44cc3e..8a9498e7c8311e582f35709c7ffc3019fda2f601 100644 (file)
@@ -277,12 +277,9 @@ static int __init init_sched_debug_procfs(void)
 {
        struct proc_dir_entry *pe;
 
-       pe = create_proc_entry("sched_debug", 0644, NULL);
+       pe = proc_create("sched_debug", 0644, NULL, &sched_debug_fops);
        if (!pe)
                return -ENOMEM;
-
-       pe->proc_fops = &sched_debug_fops;
-
        return 0;
 }
 
index 64ad0ed15992562a4b67da61e4b34746dc9c48c7..72bb4f51f9634c448ad6eb4986d8ed7f35deb1f1 100644 (file)
 
 static struct kmem_cache *sigqueue_cachep;
 
+static int __sig_ignored(struct task_struct *t, int sig)
+{
+       void __user *handler;
+
+       /* Is it explicitly or implicitly ignored? */
+
+       handler = t->sighand->action[sig - 1].sa.sa_handler;
+       return handler == SIG_IGN ||
+               (handler == SIG_DFL && sig_kernel_ignore(sig));
+}
 
 static int sig_ignored(struct task_struct *t, int sig)
 {
-       void __user * handler;
-
        /*
         * Tracers always want to know about signals..
         */
@@ -58,10 +66,7 @@ static int sig_ignored(struct task_struct *t, int sig)
        if (sigismember(&t->blocked, sig) || sigismember(&t->real_blocked, sig))
                return 0;
 
-       /* Is it explicitly or implicitly ignored? */
-       handler = t->sighand->action[sig-1].sa.sa_handler;
-       return   handler == SIG_IGN ||
-               (handler == SIG_DFL && sig_kernel_ignore(sig));
+       return __sig_ignored(t, sig);
 }
 
 /*
@@ -372,7 +377,7 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
  */
 int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
 {
-       int signr = 0;
+       int signr;
 
        /* We only dequeue private signals from ourselves, we don't let
         * signalfd steal them
@@ -405,8 +410,12 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
                        }
                }
        }
+
        recalc_sigpending();
-       if (signr && unlikely(sig_kernel_stop(signr))) {
+       if (!signr)
+               return 0;
+
+       if (unlikely(sig_kernel_stop(signr))) {
                /*
                 * Set a marker that we have dequeued a stop signal.  Our
                 * caller might release the siglock and then the pending
@@ -422,9 +431,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
                if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT))
                        tsk->signal->flags |= SIGNAL_STOP_DEQUEUED;
        }
-       if (signr &&
-            ((info->si_code & __SI_MASK) == __SI_TIMER) &&
-            info->si_sys_private) {
+       if ((info->si_code & __SI_MASK) == __SI_TIMER && info->si_sys_private) {
                /*
                 * Release the siglock to ensure proper locking order
                 * of timer locks outside of siglocks.  Note, we leave
@@ -526,21 +533,34 @@ static int rm_from_queue(unsigned long mask, struct sigpending *s)
 static int check_kill_permission(int sig, struct siginfo *info,
                                 struct task_struct *t)
 {
-       int error = -EINVAL;
+       struct pid *sid;
+       int error;
+
        if (!valid_signal(sig))
-               return error;
+               return -EINVAL;
 
-       if (info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) {
-               error = audit_signal_info(sig, t); /* Let audit system see the signal */
-               if (error)
-                       return error;
-               error = -EPERM;
-               if (((sig != SIGCONT) ||
-                       (task_session_nr(current) != task_session_nr(t)))
-                   && (current->euid ^ t->suid) && (current->euid ^ t->uid)
-                   && (current->uid ^ t->suid) && (current->uid ^ t->uid)
-                   && !capable(CAP_KILL))
+       if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info)))
+               return 0;
+
+       error = audit_signal_info(sig, t); /* Let audit system see the signal */
+       if (error)
                return error;
+
+       if ((current->euid ^ t->suid) && (current->euid ^ t->uid) &&
+           (current->uid  ^ t->suid) && (current->uid  ^ t->uid) &&
+           !capable(CAP_KILL)) {
+               switch (sig) {
+               case SIGCONT:
+                       sid = task_session(t);
+                       /*
+                        * We don't return the error if sid == NULL. The
+                        * task was unhashed, the caller must notice this.
+                        */
+                       if (!sid || sid == task_session(current))
+                               break;
+               default:
+                       return -EPERM;
+               }
        }
 
        return security_task_kill(t, info, sig, 0);
@@ -550,62 +570,44 @@ static int check_kill_permission(int sig, struct siginfo *info,
 static void do_notify_parent_cldstop(struct task_struct *tsk, int why);
 
 /*
- * Handle magic process-wide effects of stop/continue signals.
- * Unlike the signal actions, these happen immediately at signal-generation
+ * Handle magic process-wide effects of stop/continue signals. Unlike
+ * the signal actions, these happen immediately at signal-generation
  * time regardless of blocking, ignoring, or handling.  This does the
  * actual continuing for SIGCONT, but not the actual stopping for stop
- * signals.  The process stop is done as a signal action for SIG_DFL.
+ * signals. The process stop is done as a signal action for SIG_DFL.
+ *
+ * Returns true if the signal should be actually delivered, otherwise
+ * it should be dropped.
  */
-static void handle_stop_signal(int sig, struct task_struct *p)
+static int prepare_signal(int sig, struct task_struct *p)
 {
+       struct signal_struct *signal = p->signal;
        struct task_struct *t;
 
-       if (p->signal->flags & SIGNAL_GROUP_EXIT)
+       if (unlikely(signal->flags & SIGNAL_GROUP_EXIT)) {
                /*
-                * The process is in the middle of dying already.
+                * The process is in the middle of dying, nothing to do.
                 */
-               return;
-
-       if (sig_kernel_stop(sig)) {
+       } else if (sig_kernel_stop(sig)) {
                /*
                 * This is a stop signal.  Remove SIGCONT from all queues.
                 */
-               rm_from_queue(sigmask(SIGCONT), &p->signal->shared_pending);
+               rm_from_queue(sigmask(SIGCONT), &signal->shared_pending);
                t = p;
                do {
                        rm_from_queue(sigmask(SIGCONT), &t->pending);
-                       t = next_thread(t);
-               } while (t != p);
+               } while_each_thread(p, t);
        } else if (sig == SIGCONT) {
+               unsigned int why;
                /*
                 * Remove all stop signals from all queues,
                 * and wake all threads.
                 */
-               if (unlikely(p->signal->group_stop_count > 0)) {
-                       /*
-                        * There was a group stop in progress.  We'll
-                        * pretend it finished before we got here.  We are
-                        * obliged to report it to the parent: if the
-                        * SIGSTOP happened "after" this SIGCONT, then it
-                        * would have cleared this pending SIGCONT.  If it
-                        * happened "before" this SIGCONT, then the parent
-                        * got the SIGCHLD about the stop finishing before
-                        * the continue happened.  We do the notification
-                        * now, and it's as if the stop had finished and
-                        * the SIGCHLD was pending on entry to this kill.
-                        */
-                       p->signal->group_stop_count = 0;
-                       p->signal->flags = SIGNAL_STOP_CONTINUED;
-                       spin_unlock(&p->sighand->siglock);
-                       do_notify_parent_cldstop(p, CLD_STOPPED);
-                       spin_lock(&p->sighand->siglock);
-               }
-               rm_from_queue(SIG_KERNEL_STOP_MASK, &p->signal->shared_pending);
+               rm_from_queue(SIG_KERNEL_STOP_MASK, &signal->shared_pending);
                t = p;
                do {
                        unsigned int state;
                        rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending);
-                       
                        /*
                         * If there is a handler for SIGCONT, we must make
                         * sure that no thread returns to user mode before
@@ -615,7 +617,7 @@ static void handle_stop_signal(int sig, struct task_struct *p)
                         * running the handler.  With the TIF_SIGPENDING
                         * flag set, the thread will pause and acquire the
                         * siglock that we hold now and until we've queued
-                        * the pending signal. 
+                        * the pending signal.
                         *
                         * Wake up the stopped thread _after_ setting
                         * TIF_SIGPENDING
@@ -626,49 +628,163 @@ static void handle_stop_signal(int sig, struct task_struct *p)
                                state |= TASK_INTERRUPTIBLE;
                        }
                        wake_up_state(t, state);
+               } while_each_thread(p, t);
 
-                       t = next_thread(t);
-               } while (t != p);
+               /*
+                * Notify the parent with CLD_CONTINUED if we were stopped.
+                *
+                * If we were in the middle of a group stop, we pretend it
+                * was already finished, and then continued. Since SIGCHLD
+                * doesn't queue we report only CLD_STOPPED, as if the next
+                * CLD_CONTINUED was dropped.
+                */
+               why = 0;
+               if (signal->flags & SIGNAL_STOP_STOPPED)
+                       why |= SIGNAL_CLD_CONTINUED;
+               else if (signal->group_stop_count)
+                       why |= SIGNAL_CLD_STOPPED;
 
-               if (p->signal->flags & SIGNAL_STOP_STOPPED) {
+               if (why) {
                        /*
-                        * We were in fact stopped, and are now continued.
-                        * Notify the parent with CLD_CONTINUED.
+                        * The first thread which returns from finish_stop()
+                        * will take ->siglock, notice SIGNAL_CLD_MASK, and
+                        * notify its parent. See get_signal_to_deliver().
                         */
-                       p->signal->flags = SIGNAL_STOP_CONTINUED;
-                       p->signal->group_exit_code = 0;
-                       spin_unlock(&p->sighand->siglock);
-                       do_notify_parent_cldstop(p, CLD_CONTINUED);
-                       spin_lock(&p->sighand->siglock);
+                       signal->flags = why | SIGNAL_STOP_CONTINUED;
+                       signal->group_stop_count = 0;
+                       signal->group_exit_code = 0;
                } else {
                        /*
                         * We are not stopped, but there could be a stop
                         * signal in the middle of being processed after
                         * being removed from the queue.  Clear that too.
                         */
-                       p->signal->flags = 0;
+                       signal->flags &= ~SIGNAL_STOP_DEQUEUED;
                }
-       } else if (sig == SIGKILL) {
+       }
+
+       return !sig_ignored(p, sig);
+}
+
+/*
+ * Test if P wants to take SIG.  After we've checked all threads with this,
+ * it's equivalent to finding no threads not blocking SIG.  Any threads not
+ * blocking SIG were ruled out because they are not running and already
+ * have pending signals.  Such threads will dequeue from the shared queue
+ * as soon as they're available, so putting the signal on the shared queue
+ * will be equivalent to sending it to one such thread.
+ */
+static inline int wants_signal(int sig, struct task_struct *p)
+{
+       if (sigismember(&p->blocked, sig))
+               return 0;
+       if (p->flags & PF_EXITING)
+               return 0;
+       if (sig == SIGKILL)
+               return 1;
+       if (task_is_stopped_or_traced(p))
+               return 0;
+       return task_curr(p) || !signal_pending(p);
+}
+
+static void complete_signal(int sig, struct task_struct *p, int group)
+{
+       struct signal_struct *signal = p->signal;
+       struct task_struct *t;
+
+       /*
+        * Now find a thread we can wake up to take the signal off the queue.
+        *
+        * If the main thread wants the signal, it gets first crack.
+        * Probably the least surprising to the average bear.
+        */
+       if (wants_signal(sig, p))
+               t = p;
+       else if (!group || thread_group_empty(p))
+               /*
+                * There is just one thread and it does not need to be woken.
+                * It will dequeue unblocked signals before it runs again.
+                */
+               return;
+       else {
                /*
-                * Make sure that any pending stop signal already dequeued
-                * is undone by the wakeup for SIGKILL.
+                * Otherwise try to find a suitable thread.
                 */
-               p->signal->flags = 0;
+               t = signal->curr_target;
+               while (!wants_signal(sig, t)) {
+                       t = next_thread(t);
+                       if (t == signal->curr_target)
+                               /*
+                                * No thread needs to be woken.
+                                * Any eligible threads will see
+                                * the signal in the queue soon.
+                                */
+                               return;
+               }
+               signal->curr_target = t;
        }
+
+       /*
+        * Found a killable thread.  If the signal will be fatal,
+        * then start taking the whole group down immediately.
+        */
+       if (sig_fatal(p, sig) &&
+           !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) &&
+           !sigismember(&t->real_blocked, sig) &&
+           (sig == SIGKILL || !(t->ptrace & PT_PTRACED))) {
+               /*
+                * This signal will be fatal to the whole group.
+                */
+               if (!sig_kernel_coredump(sig)) {
+                       /*
+                        * Start a group exit and wake everybody up.
+                        * This way we don't have other threads
+                        * running and doing things after a slower
+                        * thread has the fatal signal pending.
+                        */
+                       signal->flags = SIGNAL_GROUP_EXIT;
+                       signal->group_exit_code = sig;
+                       signal->group_stop_count = 0;
+                       t = p;
+                       do {
+                               sigaddset(&t->pending.signal, SIGKILL);
+                               signal_wake_up(t, 1);
+                       } while_each_thread(p, t);
+                       return;
+               }
+       }
+
+       /*
+        * The signal is already in the shared-pending queue.
+        * Tell the chosen thread to wake up and dequeue it.
+        */
+       signal_wake_up(t, sig == SIGKILL);
+       return;
+}
+
+static inline int legacy_queue(struct sigpending *signals, int sig)
+{
+       return (sig < SIGRTMIN) && sigismember(&signals->signal, sig);
 }
 
 static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
-                       struct sigpending *signals)
+                       int group)
 {
-       struct sigqueue * q = NULL;
-       int ret = 0;
+       struct sigpending *pending;
+       struct sigqueue *q;
+
+       assert_spin_locked(&t->sighand->siglock);
+       if (!prepare_signal(sig, t))
+               return 0;
 
+       pending = group ? &t->signal->shared_pending : &t->pending;
        /*
-        * Deliver the signal to listening signalfds. This must be called
-        * with the sighand lock held.
+        * Short-circuit ignored signals and support queuing
+        * exactly one non-rt signal, so that we can get more
+        * detailed information about the cause of the signal.
         */
-       signalfd_notify(t, sig);
-
+       if (legacy_queue(pending, sig))
+               return 0;
        /*
         * fast-pathed signals for kernel-internal things like SIGSTOP
         * or SIGKILL.
@@ -688,7 +804,7 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
                                             (is_si_special(info) ||
                                              info->si_code >= 0)));
        if (q) {
-               list_add_tail(&q->list, &signals->list);
+               list_add_tail(&q->list, &pending->list);
                switch ((unsigned long) info) {
                case (unsigned long) SEND_SIG_NOINFO:
                        q->info.si_signo = sig;
@@ -718,13 +834,12 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
        }
 
 out_set:
-       sigaddset(&signals->signal, sig);
-       return ret;
+       signalfd_notify(t, sig);
+       sigaddset(&pending->signal, sig);
+       complete_signal(sig, t, group);
+       return 0;
 }
 
-#define LEGACY_QUEUE(sigptr, sig) \
-       (((sig) < SIGRTMIN) && sigismember(&(sigptr)->signal, (sig)))
-
 int print_fatal_signals;
 
 static void print_fatal_signal(struct pt_regs *regs, int signr)
@@ -757,29 +872,16 @@ static int __init setup_print_fatal_signals(char *str)
 
 __setup("print-fatal-signals=", setup_print_fatal_signals);
 
+int
+__group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
+{
+       return send_signal(sig, info, p, 1);
+}
+
 static int
 specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
 {
-       int ret = 0;
-
-       BUG_ON(!irqs_disabled());
-       assert_spin_locked(&t->sighand->siglock);
-
-       /* Short-circuit ignored signals.  */
-       if (sig_ignored(t, sig))
-               goto out;
-
-       /* Support queueing exactly one non-rt signal, so that we
-          can get more detailed information about the cause of
-          the signal. */
-       if (LEGACY_QUEUE(&t->pending, sig))
-               goto out;
-
-       ret = send_signal(sig, info, t, &t->pending);
-       if (!ret && !sigismember(&t->blocked, sig))
-               signal_wake_up(t, sig == SIGKILL);
-out:
-       return ret;
+       return send_signal(sig, info, t, 0);
 }
 
 /*
@@ -790,7 +892,8 @@ out:
  * since we do not want to have a signal handler that was blocked
  * be invoked when user space had explicitly blocked it.
  *
- * We don't want to have recursive SIGSEGV's etc, for example.
+ * We don't want to have recursive SIGSEGV's etc, for example,
+ * that is why we also clear SIGNAL_UNKILLABLE.
  */
 int
 force_sig_info(int sig, struct siginfo *info, struct task_struct *t)
@@ -810,6 +913,8 @@ force_sig_info(int sig, struct siginfo *info, struct task_struct *t)
                        recalc_sigpending_and_wake(t);
                }
        }
+       if (action->sa.sa_handler == SIG_DFL)
+               t->signal->flags &= ~SIGNAL_UNKILLABLE;
        ret = specific_send_sig_info(sig, info, t);
        spin_unlock_irqrestore(&t->sighand->siglock, flags);
 
@@ -822,134 +927,6 @@ force_sig_specific(int sig, struct task_struct *t)
        force_sig_info(sig, SEND_SIG_FORCED, t);
 }
 
-/*
- * Test if P wants to take SIG.  After we've checked all threads with this,
- * it's equivalent to finding no threads not blocking SIG.  Any threads not
- * blocking SIG were ruled out because they are not running and already
- * have pending signals.  Such threads will dequeue from the shared queue
- * as soon as they're available, so putting the signal on the shared queue
- * will be equivalent to sending it to one such thread.
- */
-static inline int wants_signal(int sig, struct task_struct *p)
-{
-       if (sigismember(&p->blocked, sig))
-               return 0;
-       if (p->flags & PF_EXITING)
-               return 0;
-       if (sig == SIGKILL)
-               return 1;
-       if (task_is_stopped_or_traced(p))
-               return 0;
-       return task_curr(p) || !signal_pending(p);
-}
-
-static void
-__group_complete_signal(int sig, struct task_struct *p)
-{
-       struct task_struct *t;
-
-       /*
-        * Now find a thread we can wake up to take the signal off the queue.
-        *
-        * If the main thread wants the signal, it gets first crack.
-        * Probably the least surprising to the average bear.
-        */
-       if (wants_signal(sig, p))
-               t = p;
-       else if (thread_group_empty(p))
-               /*
-                * There is just one thread and it does not need to be woken.
-                * It will dequeue unblocked signals before it runs again.
-                */
-               return;
-       else {
-               /*
-                * Otherwise try to find a suitable thread.
-                */
-               t = p->signal->curr_target;
-               if (t == NULL)
-                       /* restart balancing at this thread */
-                       t = p->signal->curr_target = p;
-
-               while (!wants_signal(sig, t)) {
-                       t = next_thread(t);
-                       if (t == p->signal->curr_target)
-                               /*
-                                * No thread needs to be woken.
-                                * Any eligible threads will see
-                                * the signal in the queue soon.
-                                */
-                               return;
-               }
-               p->signal->curr_target = t;
-       }
-
-       /*
-        * Found a killable thread.  If the signal will be fatal,
-        * then start taking the whole group down immediately.
-        */
-       if (sig_fatal(p, sig) && !(p->signal->flags & SIGNAL_GROUP_EXIT) &&
-           !sigismember(&t->real_blocked, sig) &&
-           (sig == SIGKILL || !(t->ptrace & PT_PTRACED))) {
-               /*
-                * This signal will be fatal to the whole group.
-                */
-               if (!sig_kernel_coredump(sig)) {
-                       /*
-                        * Start a group exit and wake everybody up.
-                        * This way we don't have other threads
-                        * running and doing things after a slower
-                        * thread has the fatal signal pending.
-                        */
-                       p->signal->flags = SIGNAL_GROUP_EXIT;
-                       p->signal->group_exit_code = sig;
-                       p->signal->group_stop_count = 0;
-                       t = p;
-                       do {
-                               sigaddset(&t->pending.signal, SIGKILL);
-                               signal_wake_up(t, 1);
-                       } while_each_thread(p, t);
-                       return;
-               }
-       }
-
-       /*
-        * The signal is already in the shared-pending queue.
-        * Tell the chosen thread to wake up and dequeue it.
-        */
-       signal_wake_up(t, sig == SIGKILL);
-       return;
-}
-
-int
-__group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
-{
-       int ret = 0;
-
-       assert_spin_locked(&p->sighand->siglock);
-       handle_stop_signal(sig, p);
-
-       /* Short-circuit ignored signals.  */
-       if (sig_ignored(p, sig))
-               return ret;
-
-       if (LEGACY_QUEUE(&p->signal->shared_pending, sig))
-               /* This is a non-RT signal and we already have one queued.  */
-               return ret;
-
-       /*
-        * Put this signal on the shared-pending queue, or fail with EAGAIN.
-        * We always use the shared queue for process-wide signals,
-        * to avoid several races.
-        */
-       ret = send_signal(sig, info, p, &p->signal->shared_pending);
-       if (unlikely(ret))
-               return ret;
-
-       __group_complete_signal(sig, p);
-       return 0;
-}
-
 /*
  * Nuke all other threads in the group.
  */
@@ -978,13 +955,11 @@ int __fatal_signal_pending(struct task_struct *tsk)
 }
 EXPORT_SYMBOL(__fatal_signal_pending);
 
-/*
- * Must be called under rcu_read_lock() or with tasklist_lock read-held.
- */
 struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long *flags)
 {
        struct sighand_struct *sighand;
 
+       rcu_read_lock();
        for (;;) {
                sighand = rcu_dereference(tsk->sighand);
                if (unlikely(sighand == NULL))
@@ -995,6 +970,7 @@ struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long
                        break;
                spin_unlock_irqrestore(&sighand->siglock, *flags);
        }
+       rcu_read_unlock();
 
        return sighand;
 }
@@ -1043,9 +1019,6 @@ int kill_pid_info(int sig, struct siginfo *info, struct pid *pid)
        struct task_struct *p;
 
        rcu_read_lock();
-       if (unlikely(sig_needs_tasklist(sig)))
-               read_lock(&tasklist_lock);
-
 retry:
        p = pid_task(pid, PIDTYPE_PID);
        if (p) {
@@ -1059,10 +1032,8 @@ retry:
                         */
                        goto retry;
        }
-
-       if (unlikely(sig_needs_tasklist(sig)))
-               read_unlock(&tasklist_lock);
        rcu_read_unlock();
+
        return error;
 }
 
@@ -1159,8 +1130,7 @@ static int kill_something_info(int sig, struct siginfo *info, int pid)
  */
 
 /*
- * These two are the most common entry points.  They send a signal
- * just to the specific thread.
+ * The caller must ensure the task can't exit.
  */
 int
 send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
@@ -1175,17 +1145,9 @@ send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
        if (!valid_signal(sig))
                return -EINVAL;
 
-       /*
-        * We need the tasklist lock even for the specific
-        * thread case (when we don't need to follow the group
-        * lists) in order to avoid races with "p->sighand"
-        * going away or changing from under us.
-        */
-       read_lock(&tasklist_lock);  
        spin_lock_irqsave(&p->sighand->siglock, flags);
        ret = specific_send_sig_info(sig, info, p);
        spin_unlock_irqrestore(&p->sighand->siglock, flags);
-       read_unlock(&tasklist_lock);
        return ret;
 }
 
@@ -1291,28 +1253,24 @@ void sigqueue_free(struct sigqueue *q)
        __sigqueue_free(q);
 }
 
-int send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
+int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group)
 {
+       int sig = q->info.si_signo;
+       struct sigpending *pending;
        unsigned long flags;
-       int ret = 0;
+       int ret;
 
        BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
 
-       /*
-        * The rcu based delayed sighand destroy makes it possible to
-        * run this without tasklist lock held. The task struct itself
-        * cannot go away as create_timer did get_task_struct().
-        *
-        * We return -1, when the task is marked exiting, so
-        * posix_timer_event can redirect it to the group leader
-        */
-       rcu_read_lock();
+       ret = -1;
+       if (!likely(lock_task_sighand(t, &flags)))
+               goto ret;
 
-       if (!likely(lock_task_sighand(p, &flags))) {
-               ret = -1;
-               goto out_err;
-       }
+       ret = 1; /* the signal is ignored */
+       if (!prepare_signal(sig, t))
+               goto out;
 
+       ret = 0;
        if (unlikely(!list_empty(&q->list))) {
                /*
                 * If an SI_TIMER entry is already queue just increment
@@ -1322,77 +1280,15 @@ int send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
                q->info.si_overrun++;
                goto out;
        }
-       /* Short-circuit ignored signals.  */
-       if (sig_ignored(p, sig)) {
-               ret = 1;
-               goto out;
-       }
-       /*
-        * Deliver the signal to listening signalfds. This must be called
-        * with the sighand lock held.
-        */
-       signalfd_notify(p, sig);
-
-       list_add_tail(&q->list, &p->pending.list);
-       sigaddset(&p->pending.signal, sig);
-       if (!sigismember(&p->blocked, sig))
-               signal_wake_up(p, sig == SIGKILL);
-
-out:
-       unlock_task_sighand(p, &flags);
-out_err:
-       rcu_read_unlock();
-
-       return ret;
-}
-
-int
-send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
-{
-       unsigned long flags;
-       int ret = 0;
-
-       BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
-
-       read_lock(&tasklist_lock);
-       /* Since it_lock is held, p->sighand cannot be NULL. */
-       spin_lock_irqsave(&p->sighand->siglock, flags);
-       handle_stop_signal(sig, p);
-
-       /* Short-circuit ignored signals.  */
-       if (sig_ignored(p, sig)) {
-               ret = 1;
-               goto out;
-       }
 
-       if (unlikely(!list_empty(&q->list))) {
-               /*
-                * If an SI_TIMER entry is already queue just increment
-                * the overrun count.  Other uses should not try to
-                * send the signal multiple times.
-                */
-               BUG_ON(q->info.si_code != SI_TIMER);
-               q->info.si_overrun++;
-               goto out;
-       } 
-       /*
-        * Deliver the signal to listening signalfds. This must be called
-        * with the sighand lock held.
-        */
-       signalfd_notify(p, sig);
-
-       /*
-        * Put this signal on the shared-pending queue.
-        * We always use the shared queue for process-wide signals,
-        * to avoid several races.
-        */
-       list_add_tail(&q->list, &p->signal->shared_pending.list);
-       sigaddset(&p->signal->shared_pending.signal, sig);
-
-       __group_complete_signal(sig, p);
+       signalfd_notify(t, sig);
+       pending = group ? &t->signal->shared_pending : &t->pending;
+       list_add_tail(&q->list, &pending->list);
+       sigaddset(&pending->signal, sig);
+       complete_signal(sig, t, group);
 out:
-       spin_unlock_irqrestore(&p->sighand->siglock, flags);
-       read_unlock(&tasklist_lock);
+       unlock_task_sighand(t, &flags);
+ret:
        return ret;
 }
 
@@ -1723,8 +1619,9 @@ static int do_signal_stop(int signr)
        } else {
                struct task_struct *t;
 
-               if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED) ||
-                   unlikely(sig->group_exit_task))
+               if (unlikely((sig->flags & (SIGNAL_STOP_DEQUEUED | SIGNAL_UNKILLABLE))
+                                        != SIGNAL_STOP_DEQUEUED) ||
+                   unlikely(signal_group_exit(sig)))
                        return 0;
                /*
                 * There is no group stop already in progress.
@@ -1799,8 +1696,9 @@ static int ptrace_signal(int signr, siginfo_t *info,
 int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
                          struct pt_regs *regs, void *cookie)
 {
-       sigset_t *mask = &current->blocked;
-       int signr = 0;
+       struct sighand_struct *sighand = current->sighand;
+       struct signal_struct *signal = current->signal;
+       int signr;
 
 relock:
        /*
@@ -1811,16 +1709,32 @@ relock:
         */
        try_to_freeze();
 
-       spin_lock_irq(&current->sighand->siglock);
+       spin_lock_irq(&sighand->siglock);
+       /*
+        * Every stopped thread goes here after wakeup. Check to see if
+        * we should notify the parent, prepare_signal(SIGCONT) encodes
+        * the CLD_ si_code into SIGNAL_CLD_MASK bits.
+        */
+       if (unlikely(signal->flags & SIGNAL_CLD_MASK)) {
+               int why = (signal->flags & SIGNAL_STOP_CONTINUED)
+                               ? CLD_CONTINUED : CLD_STOPPED;
+               signal->flags &= ~SIGNAL_CLD_MASK;
+               spin_unlock_irq(&sighand->siglock);
+
+               read_lock(&tasklist_lock);
+               do_notify_parent_cldstop(current->group_leader, why);
+               read_unlock(&tasklist_lock);
+               goto relock;
+       }
+
        for (;;) {
                struct k_sigaction *ka;
 
-               if (unlikely(current->signal->group_stop_count > 0) &&
+               if (unlikely(signal->group_stop_count > 0) &&
                    do_signal_stop(0))
                        goto relock;
 
-               signr = dequeue_signal(current, mask, info);
-
+               signr = dequeue_signal(current, &current->blocked, info);
                if (!signr)
                        break; /* will return 0 */
 
@@ -1830,7 +1744,7 @@ relock:
                                continue;
                }
 
-               ka = &current->sighand->action[signr-1];
+               ka = &sighand->action[signr-1];
                if (ka->sa.sa_handler == SIG_IGN) /* Do nothing.  */
                        continue;
                if (ka->sa.sa_handler != SIG_DFL) {
@@ -1852,7 +1766,8 @@ relock:
                /*
                 * Global init gets no signals it doesn't want.
                 */
-               if (is_global_init(current))
+               if (unlikely(signal->flags & SIGNAL_UNKILLABLE) &&
+                   !signal_group_exit(signal))
                        continue;
 
                if (sig_kernel_stop(signr)) {
@@ -1867,14 +1782,14 @@ relock:
                         * We need to check for that and bail out if necessary.
                         */
                        if (signr != SIGSTOP) {
-                               spin_unlock_irq(&current->sighand->siglock);
+                               spin_unlock_irq(&sighand->siglock);
 
                                /* signals can be posted during this window */
 
                                if (is_current_pgrp_orphaned())
                                        goto relock;
 
-                               spin_lock_irq(&current->sighand->siglock);
+                               spin_lock_irq(&sighand->siglock);
                        }
 
                        if (likely(do_signal_stop(signr))) {
@@ -1889,15 +1804,16 @@ relock:
                        continue;
                }
 
-               spin_unlock_irq(&current->sighand->siglock);
+               spin_unlock_irq(&sighand->siglock);
 
                /*
                 * Anything else is fatal, maybe with a core dump.
                 */
                current->flags |= PF_SIGNALED;
-               if ((signr != SIGKILL) && print_fatal_signals)
-                       print_fatal_signal(regs, signr);
+
                if (sig_kernel_coredump(signr)) {
+                       if (print_fatal_signals)
+                               print_fatal_signal(regs, signr);
                        /*
                         * If it was able to dump core, this kills all
                         * other threads in the group and synchronizes with
@@ -1915,7 +1831,7 @@ relock:
                do_group_exit(signr);
                /* NOTREACHED */
        }
-       spin_unlock_irq(&current->sighand->siglock);
+       spin_unlock_irq(&sighand->siglock);
        return signr;
 }
 
@@ -2259,6 +2175,7 @@ static int do_tkill(int tgid, int pid, int sig)
        int error;
        struct siginfo info;
        struct task_struct *p;
+       unsigned long flags;
 
        error = -ESRCH;
        info.si_signo = sig;
@@ -2267,22 +2184,24 @@ static int do_tkill(int tgid, int pid, int sig)
        info.si_pid = task_tgid_vnr(current);
        info.si_uid = current->uid;
 
-       read_lock(&tasklist_lock);
+       rcu_read_lock();
        p = find_task_by_vpid(pid);
        if (p && (tgid <= 0 || task_tgid_vnr(p) == tgid)) {
                error = check_kill_permission(sig, &info, p);
                /*
                 * The null signal is a permissions and process existence
                 * probe.  No signal is actually delivered.
+                *
+                * If lock_task_sighand() fails we pretend the task dies
+                * after receiving the signal. The window is tiny, and the
+                * signal is private anyway.
                 */
-               if (!error && sig && p->sighand) {
-                       spin_lock_irq(&p->sighand->siglock);
-                       handle_stop_signal(sig, p);
+               if (!error && sig && lock_task_sighand(p, &flags)) {
                        error = specific_send_sig_info(sig, &info, p);
-                       spin_unlock_irq(&p->sighand->siglock);
+                       unlock_task_sighand(p, &flags);
                }
        }
-       read_unlock(&tasklist_lock);
+       rcu_read_unlock();
 
        return error;
 }
@@ -2339,13 +2258,14 @@ sys_rt_sigqueueinfo(int pid, int sig, siginfo_t __user *uinfo)
 
 int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
 {
+       struct task_struct *t = current;
        struct k_sigaction *k;
        sigset_t mask;
 
        if (!valid_signal(sig) || sig < 1 || (act && sig_kernel_only(sig)))
                return -EINVAL;
 
-       k = &current->sighand->action[sig-1];
+       k = &t->sighand->action[sig-1];
 
        spin_lock_irq(&current->sighand->siglock);
        if (oact)
@@ -2366,9 +2286,7 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
                 *   (for example, SIGCHLD), shall cause the pending signal to
                 *   be discarded, whether or not it is blocked"
                 */
-               if (act->sa.sa_handler == SIG_IGN ||
-                  (act->sa.sa_handler == SIG_DFL && sig_kernel_ignore(sig))) {
-                       struct task_struct *t = current;
+               if (__sig_ignored(t, sig)) {
                        sigemptyset(&mask);
                        sigaddset(&mask, sig);
                        rm_from_queue_full(&mask, &t->signal->shared_pending);
@@ -2623,7 +2541,7 @@ asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
 
        current->state = TASK_INTERRUPTIBLE;
        schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
+       set_restore_sigmask();
        return -ERESTARTNOHAND;
 }
 #endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */
index f2a4513669536d6370783c798d5fea460121aee3..895d2d4c94931e5136c9d063adf19d3d7999b0a6 100644 (file)
@@ -978,8 +978,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
                goto out;
 
        if (task_pgrp(p) != pgrp) {
-               detach_pid(p, PIDTYPE_PGID);
-               attach_pid(p, PIDTYPE_PGID, pgrp);
+               change_pid(p, PIDTYPE_PGID, pgrp);
                set_task_pgrp(p, pid_nr(pgrp));
        }
 
@@ -992,54 +991,67 @@ out:
 
 asmlinkage long sys_getpgid(pid_t pid)
 {
+       struct task_struct *p;
+       struct pid *grp;
+       int retval;
+
+       rcu_read_lock();
        if (!pid)
-               return task_pgrp_vnr(current);
+               grp = task_pgrp(current);
        else {
-               int retval;
-               struct task_struct *p;
-
-               read_lock(&tasklist_lock);
-               p = find_task_by_vpid(pid);
                retval = -ESRCH;
-               if (p) {
-                       retval = security_task_getpgid(p);
-                       if (!retval)
-                               retval = task_pgrp_vnr(p);
-               }
-               read_unlock(&tasklist_lock);
-               return retval;
+               p = find_task_by_vpid(pid);
+               if (!p)
+                       goto out;
+               grp = task_pgrp(p);
+               if (!grp)
+                       goto out;
+
+               retval = security_task_getpgid(p);
+               if (retval)
+                       goto out;
        }
+       retval = pid_vnr(grp);
+out:
+       rcu_read_unlock();
+       return retval;
 }
 
 #ifdef __ARCH_WANT_SYS_GETPGRP
 
 asmlinkage long sys_getpgrp(void)
 {
-       /* SMP - assuming writes are word atomic this is fine */
-       return task_pgrp_vnr(current);
+       return sys_getpgid(0);
 }
 
 #endif
 
 asmlinkage long sys_getsid(pid_t pid)
 {
+       struct task_struct *p;
+       struct pid *sid;
+       int retval;
+
+       rcu_read_lock();
        if (!pid)
-               return task_session_vnr(current);
+               sid = task_session(current);
        else {
-               int retval;
-               struct task_struct *p;
-
-               rcu_read_lock();
-               p = find_task_by_vpid(pid);
                retval = -ESRCH;
-               if (p) {
-                       retval = security_task_getsid(p);
-                       if (!retval)
-                               retval = task_session_vnr(p);
-               }
-               rcu_read_unlock();
-               return retval;
+               p = find_task_by_vpid(pid);
+               if (!p)
+                       goto out;
+               sid = task_session(p);
+               if (!sid)
+                       goto out;
+
+               retval = security_task_getsid(p);
+               if (retval)
+                       goto out;
        }
+       retval = pid_vnr(sid);
+out:
+       rcu_read_unlock();
+       return retval;
 }
 
 asmlinkage long sys_setsid(void)
@@ -1545,6 +1557,19 @@ out:
  *
  */
 
+static void accumulate_thread_rusage(struct task_struct *t, struct rusage *r,
+                                    cputime_t *utimep, cputime_t *stimep)
+{
+       *utimep = cputime_add(*utimep, t->utime);
+       *stimep = cputime_add(*stimep, t->stime);
+       r->ru_nvcsw += t->nvcsw;
+       r->ru_nivcsw += t->nivcsw;
+       r->ru_minflt += t->min_flt;
+       r->ru_majflt += t->maj_flt;
+       r->ru_inblock += task_io_get_inblock(t);
+       r->ru_oublock += task_io_get_oublock(t);
+}
+
 static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
 {
        struct task_struct *t;
@@ -1554,12 +1579,14 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
        memset((char *) r, 0, sizeof *r);
        utime = stime = cputime_zero;
 
-       rcu_read_lock();
-       if (!lock_task_sighand(p, &flags)) {
-               rcu_read_unlock();
-               return;
+       if (who == RUSAGE_THREAD) {
+               accumulate_thread_rusage(p, r, &utime, &stime);
+               goto out;
        }
 
+       if (!lock_task_sighand(p, &flags))
+               return;
+
        switch (who) {
                case RUSAGE_BOTH:
                case RUSAGE_CHILDREN:
@@ -1586,14 +1613,7 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
                        r->ru_oublock += p->signal->oublock;
                        t = p;
                        do {
-                               utime = cputime_add(utime, t->utime);
-                               stime = cputime_add(stime, t->stime);
-                               r->ru_nvcsw += t->nvcsw;
-                               r->ru_nivcsw += t->nivcsw;
-                               r->ru_minflt += t->min_flt;
-                               r->ru_majflt += t->maj_flt;
-                               r->ru_inblock += task_io_get_inblock(t);
-                               r->ru_oublock += task_io_get_oublock(t);
+                               accumulate_thread_rusage(t, r, &utime, &stime);
                                t = next_thread(t);
                        } while (t != p);
                        break;
@@ -1601,10 +1621,9 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
                default:
                        BUG();
        }
-
        unlock_task_sighand(p, &flags);
-       rcu_read_unlock();
 
+out:
        cputime_to_timeval(utime, &r->ru_utime);
        cputime_to_timeval(stime, &r->ru_stime);
 }
@@ -1618,7 +1637,8 @@ int getrusage(struct task_struct *p, int who, struct rusage __user *ru)
 
 asmlinkage long sys_getrusage(int who, struct rusage __user *ru)
 {
-       if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
+       if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN &&
+           who != RUSAGE_THREAD)
                return -EINVAL;
        return getrusage(current, who, ru);
 }
index fd3364827ccf0a838c79fe240016c93cedd508e4..d7ffdc59816ad3f822389d508f3c5ff1b030578d 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/writeback.h>
 #include <linux/hugetlb.h>
 #include <linux/initrd.h>
+#include <linux/key.h>
 #include <linux/times.h>
 #include <linux/limits.h>
 #include <linux/dcache.h>
@@ -144,12 +145,6 @@ extern int no_unaligned_warning;
 extern int max_lock_depth;
 #endif
 
-#ifdef CONFIG_SYSCTL_SYSCALL
-static int parse_table(int __user *, int, void __user *, size_t __user *,
-               void __user *, size_t, struct ctl_table *);
-#endif
-
-
 #ifdef CONFIG_PROC_SYSCTL
 static int proc_do_cad_pid(struct ctl_table *table, int write, struct file *filp,
                  void __user *buffer, size_t *lenp, loff_t *ppos);
@@ -809,6 +804,14 @@ static struct ctl_table kern_table[] = {
                .proc_handler   = &proc_dostring,
                .strategy       = &sysctl_string,
        },
+#ifdef CONFIG_KEYS
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "keys",
+               .mode           = 0555,
+               .child          = key_sysctls,
+       },
+#endif
 /*
  * NOTE: do not add new entries to this table unless you have read
  * Documentation/sysctl/ctl_unnumbered.txt
@@ -1430,6 +1433,76 @@ void register_sysctl_root(struct ctl_table_root *root)
 }
 
 #ifdef CONFIG_SYSCTL_SYSCALL
+/* Perform the actual read/write of a sysctl table entry. */
+static int do_sysctl_strategy(struct ctl_table_root *root,
+                       struct ctl_table *table,
+                       int __user *name, int nlen,
+                       void __user *oldval, size_t __user *oldlenp,
+                       void __user *newval, size_t newlen)
+{
+       int op = 0, rc;
+
+       if (oldval)
+               op |= 004;
+       if (newval)
+               op |= 002;
+       if (sysctl_perm(root, table, op))
+               return -EPERM;
+
+       if (table->strategy) {
+               rc = table->strategy(table, name, nlen, oldval, oldlenp,
+                                    newval, newlen);
+               if (rc < 0)
+                       return rc;
+               if (rc > 0)
+                       return 0;
+       }
+
+       /* If there is no strategy routine, or if the strategy returns
+        * zero, proceed with automatic r/w */
+       if (table->data && table->maxlen) {
+               rc = sysctl_data(table, name, nlen, oldval, oldlenp,
+                                newval, newlen);
+               if (rc < 0)
+                       return rc;
+       }
+       return 0;
+}
+
+static int parse_table(int __user *name, int nlen,
+                      void __user *oldval, size_t __user *oldlenp,
+                      void __user *newval, size_t newlen,
+                      struct ctl_table_root *root,
+                      struct ctl_table *table)
+{
+       int n;
+repeat:
+       if (!nlen)
+               return -ENOTDIR;
+       if (get_user(n, name))
+               return -EFAULT;
+       for ( ; table->ctl_name || table->procname; table++) {
+               if (!table->ctl_name)
+                       continue;
+               if (n == table->ctl_name) {
+                       int error;
+                       if (table->child) {
+                               if (sysctl_perm(root, table, 001))
+                                       return -EPERM;
+                               name++;
+                               nlen--;
+                               table = table->child;
+                               goto repeat;
+                       }
+                       error = do_sysctl_strategy(root, table, name, nlen,
+                                                  oldval, oldlenp,
+                                                  newval, newlen);
+                       return error;
+               }
+       }
+       return -ENOTDIR;
+}
+
 int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
               void __user *newval, size_t newlen)
 {
@@ -1447,7 +1520,8 @@ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *ol
        for (head = sysctl_head_next(NULL); head;
                        head = sysctl_head_next(head)) {
                error = parse_table(name, nlen, oldval, oldlenp, 
-                                       newval, newlen, head->ctl_table);
+                                       newval, newlen,
+                                       head->root, head->ctl_table);
                if (error != -ENOTDIR) {
                        sysctl_head_finish(head);
                        break;
@@ -1493,84 +1567,22 @@ static int test_perm(int mode, int op)
        return -EACCES;
 }
 
-int sysctl_perm(struct ctl_table *table, int op)
+int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op)
 {
        int error;
+       int mode;
+
        error = security_sysctl(table, op);
        if (error)
                return error;
-       return test_perm(table->mode, op);
-}
-
-#ifdef CONFIG_SYSCTL_SYSCALL
-static int parse_table(int __user *name, int nlen,
-                      void __user *oldval, size_t __user *oldlenp,
-                      void __user *newval, size_t newlen,
-                      struct ctl_table *table)
-{
-       int n;
-repeat:
-       if (!nlen)
-               return -ENOTDIR;
-       if (get_user(n, name))
-               return -EFAULT;
-       for ( ; table->ctl_name || table->procname; table++) {
-               if (!table->ctl_name)
-                       continue;
-               if (n == table->ctl_name) {
-                       int error;
-                       if (table->child) {
-                               if (sysctl_perm(table, 001))
-                                       return -EPERM;
-                               name++;
-                               nlen--;
-                               table = table->child;
-                               goto repeat;
-                       }
-                       error = do_sysctl_strategy(table, name, nlen,
-                                                  oldval, oldlenp,
-                                                  newval, newlen);
-                       return error;
-               }
-       }
-       return -ENOTDIR;
-}
 
-/* Perform the actual read/write of a sysctl table entry. */
-int do_sysctl_strategy (struct ctl_table *table,
-                       int __user *name, int nlen,
-                       void __user *oldval, size_t __user *oldlenp,
-                       void __user *newval, size_t newlen)
-{
-       int op = 0, rc;
-
-       if (oldval)
-               op |= 004;
-       if (newval) 
-               op |= 002;
-       if (sysctl_perm(table, op))
-               return -EPERM;
+       if (root->permissions)
+               mode = root->permissions(root, current->nsproxy, table);
+       else
+               mode = table->mode;
 
-       if (table->strategy) {
-               rc = table->strategy(table, name, nlen, oldval, oldlenp,
-                                    newval, newlen);
-               if (rc < 0)
-                       return rc;
-               if (rc > 0)
-                       return 0;
-       }
-
-       /* If there is no strategy routine, or if the strategy returns
-        * zero, proceed with automatic r/w */
-       if (table->data && table->maxlen) {
-               rc = sysctl_data(table, name, nlen, oldval, oldlenp,
-                                newval, newlen);
-               if (rc < 0)
-                       return rc;
-       }
-       return 0;
+       return test_perm(mode, op);
 }
-#endif /* CONFIG_SYSCTL_SYSCALL */
 
 static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table)
 {
@@ -1583,9 +1595,13 @@ static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table)
 
 static __init int sysctl_init(void)
 {
-       int err;
        sysctl_set_parent(NULL, root_table);
-       err = sysctl_check_table(current->nsproxy, root_table);
+#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
+       {
+               int err;
+               err = sysctl_check_table(current->nsproxy, root_table);
+       }
+#endif
        return 0;
 }
 
@@ -1712,10 +1728,12 @@ struct ctl_table_header *__register_sysctl_paths(
        header->unregistering = NULL;
        header->root = root;
        sysctl_set_parent(NULL, header->ctl_table);
+#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
        if (sysctl_check_table(namespaces, header->ctl_table)) {
                kfree(header);
                return NULL;
        }
+#endif
        spin_lock(&sysctl_lock);
        header_list = lookup_header_list(root, namespaces);
        list_add_tail(&header->ctl_entry, header_list);
index 07e86a828073bc7ebffdcdb67c3ee726be9a5705..4a23517169a6495cf1aa1bc689137e1c38698c62 100644 (file)
@@ -183,7 +183,7 @@ static int fill_pid(pid_t pid, struct task_struct *tsk,
 
        if (!tsk) {
                rcu_read_lock();
-               tsk = find_task_by_pid(pid);
+               tsk = find_task_by_vpid(pid);
                if (tsk)
                        get_task_struct(tsk);
                rcu_read_unlock();
@@ -230,7 +230,7 @@ static int fill_tgid(pid_t tgid, struct task_struct *first,
         */
        rcu_read_lock();
        if (!first)
-               first = find_task_by_pid(tgid);
+               first = find_task_by_vpid(tgid);
 
        if (!first || !lock_task_sighand(first, &flags))
                goto out;
@@ -547,7 +547,7 @@ void taskstats_exit(struct task_struct *tsk, int group_dead)
        if (!stats)
                goto err;
 
-       rc = fill_pid(tsk->pid, tsk, stats);
+       rc = fill_pid(-1, tsk, stats);
        if (rc < 0)
                goto err;
 
index 35d373a98782bbe0f02cb62535a4576a398dd61a..86729042e4cd067b1168fe8ed5cc2da01576cf03 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/syscalls.h>
 #include <linux/security.h>
 #include <linux/fs.h>
+#include <linux/slab.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
index 67fe8fc21fb130fd906ef050be927dc23d80fa02..a40e20fd00010d000a3dfc2406888b2f81146db6 100644 (file)
@@ -278,12 +278,9 @@ static int __init init_timer_list_procfs(void)
 {
        struct proc_dir_entry *pe;
 
-       pe = create_proc_entry("timer_list", 0644, NULL);
+       pe = proc_create("timer_list", 0644, NULL, &timer_list_fops);
        if (!pe)
                return -ENOMEM;
-
-       pe->proc_fops = &timer_list_fops;
-
        return 0;
 }
 __initcall(init_timer_list_procfs);
index 417da8c5bc7248018d915f40d0aedfa579679e8a..c994530d166da4fde2bed268f7a3ecfe661e93a8 100644 (file)
@@ -415,12 +415,9 @@ static int __init init_tstats_procfs(void)
 {
        struct proc_dir_entry *pe;
 
-       pe = create_proc_entry("timer_stats", 0644, NULL);
+       pe = proc_create("timer_stats", 0644, NULL, &tstats_fops);
        if (!pe)
                return -ENOMEM;
-
-       pe->proc_fops = &tstats_fops;
-
        return 0;
 }
 __initcall(init_tstats_procfs);
index f3d35d4ea42eff89e09db3e741022c22e593c3a9..ceacc6626572a7c2e2c345ba136bd456a267ba64 100644 (file)
@@ -320,14 +320,130 @@ static void timer_stats_account_timer(struct timer_list *timer)
 static void timer_stats_account_timer(struct timer_list *timer) {}
 #endif
 
-/**
- * init_timer - initialize a timer.
- * @timer: the timer to be initialized
- *
- * init_timer() must be done to a timer prior calling *any* of the
- * other timer functions.
+#ifdef CONFIG_DEBUG_OBJECTS_TIMERS
+
+static struct debug_obj_descr timer_debug_descr;
+
+/*
+ * fixup_init is called when:
+ * - an active object is initialized
  */
-void init_timer(struct timer_list *timer)
+static int timer_fixup_init(void *addr, enum debug_obj_state state)
+{
+       struct timer_list *timer = addr;
+
+       switch (state) {
+       case ODEBUG_STATE_ACTIVE:
+               del_timer_sync(timer);
+               debug_object_init(timer, &timer_debug_descr);
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+/*
+ * fixup_activate is called when:
+ * - an active object is activated
+ * - an unknown object is activated (might be a statically initialized object)
+ */
+static int timer_fixup_activate(void *addr, enum debug_obj_state state)
+{
+       struct timer_list *timer = addr;
+
+       switch (state) {
+
+       case ODEBUG_STATE_NOTAVAILABLE:
+               /*
+                * This is not really a fixup. The timer was
+                * statically initialized. We just make sure that it
+                * is tracked in the object tracker.
+                */
+               if (timer->entry.next == NULL &&
+                   timer->entry.prev == TIMER_ENTRY_STATIC) {
+                       debug_object_init(timer, &timer_debug_descr);
+                       debug_object_activate(timer, &timer_debug_descr);
+                       return 0;
+               } else {
+                       WARN_ON_ONCE(1);
+               }
+               return 0;
+
+       case ODEBUG_STATE_ACTIVE:
+               WARN_ON(1);
+
+       default:
+               return 0;
+       }
+}
+
+/*
+ * fixup_free is called when:
+ * - an active object is freed
+ */
+static int timer_fixup_free(void *addr, enum debug_obj_state state)
+{
+       struct timer_list *timer = addr;
+
+       switch (state) {
+       case ODEBUG_STATE_ACTIVE:
+               del_timer_sync(timer);
+               debug_object_free(timer, &timer_debug_descr);
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static struct debug_obj_descr timer_debug_descr = {
+       .name           = "timer_list",
+       .fixup_init     = timer_fixup_init,
+       .fixup_activate = timer_fixup_activate,
+       .fixup_free     = timer_fixup_free,
+};
+
+static inline void debug_timer_init(struct timer_list *timer)
+{
+       debug_object_init(timer, &timer_debug_descr);
+}
+
+static inline void debug_timer_activate(struct timer_list *timer)
+{
+       debug_object_activate(timer, &timer_debug_descr);
+}
+
+static inline void debug_timer_deactivate(struct timer_list *timer)
+{
+       debug_object_deactivate(timer, &timer_debug_descr);
+}
+
+static inline void debug_timer_free(struct timer_list *timer)
+{
+       debug_object_free(timer, &timer_debug_descr);
+}
+
+static void __init_timer(struct timer_list *timer);
+
+void init_timer_on_stack(struct timer_list *timer)
+{
+       debug_object_init_on_stack(timer, &timer_debug_descr);
+       __init_timer(timer);
+}
+EXPORT_SYMBOL_GPL(init_timer_on_stack);
+
+void destroy_timer_on_stack(struct timer_list *timer)
+{
+       debug_object_free(timer, &timer_debug_descr);
+}
+EXPORT_SYMBOL_GPL(destroy_timer_on_stack);
+
+#else
+static inline void debug_timer_init(struct timer_list *timer) { }
+static inline void debug_timer_activate(struct timer_list *timer) { }
+static inline void debug_timer_deactivate(struct timer_list *timer) { }
+#endif
+
+static void __init_timer(struct timer_list *timer)
 {
        timer->entry.next = NULL;
        timer->base = __raw_get_cpu_var(tvec_bases);
@@ -337,6 +453,19 @@ void init_timer(struct timer_list *timer)
        memset(timer->start_comm, 0, TASK_COMM_LEN);
 #endif
 }
+
+/**
+ * init_timer - initialize a timer.
+ * @timer: the timer to be initialized
+ *
+ * init_timer() must be done to a timer prior calling *any* of the
+ * other timer functions.
+ */
+void init_timer(struct timer_list *timer)
+{
+       debug_timer_init(timer);
+       __init_timer(timer);
+}
 EXPORT_SYMBOL(init_timer);
 
 void init_timer_deferrable(struct timer_list *timer)
@@ -351,6 +480,8 @@ static inline void detach_timer(struct timer_list *timer,
 {
        struct list_head *entry = &timer->entry;
 
+       debug_timer_deactivate(timer);
+
        __list_del(entry->prev, entry->next);
        if (clear_pending)
                entry->next = NULL;
@@ -405,6 +536,8 @@ int __mod_timer(struct timer_list *timer, unsigned long expires)
                ret = 1;
        }
 
+       debug_timer_activate(timer);
+
        new_base = __get_cpu_var(tvec_bases);
 
        if (base != new_base) {
@@ -450,6 +583,7 @@ void add_timer_on(struct timer_list *timer, int cpu)
        BUG_ON(timer_pending(timer) || !timer->function);
        spin_lock_irqsave(&base->lock, flags);
        timer_set_base(timer, base);
+       debug_timer_activate(timer);
        internal_add_timer(base, timer);
        /*
         * Check whether the other CPU is idle and needs to be
@@ -1086,11 +1220,14 @@ signed long __sched schedule_timeout(signed long timeout)
 
        expire = timeout + jiffies;
 
-       setup_timer(&timer, process_timeout, (unsigned long)current);
+       setup_timer_on_stack(&timer, process_timeout, (unsigned long)current);
        __mod_timer(&timer, expire);
        schedule();
        del_singleshot_timer_sync(&timer);
 
+       /* Remove the timer from the object tracker */
+       destroy_timer_on_stack(&timer);
+
        timeout = expire - jiffies;
 
  out:
index debce602bfddd9f117ec5fb98ad0023176eb7f7b..865ecf57a09604cc1307407cc99f90c1cecc5309 100644 (file)
@@ -53,10 +53,6 @@ struct user_struct root_user = {
        .files          = ATOMIC_INIT(0),
        .sigpending     = ATOMIC_INIT(0),
        .locked_shm     = 0,
-#ifdef CONFIG_KEYS
-       .uid_keyring    = &root_user_keyring,
-       .session_keyring = &root_session_keyring,
-#endif
 #ifdef CONFIG_USER_SCHED
        .tg             = &init_task_group,
 #endif
@@ -388,7 +384,7 @@ void free_uid(struct user_struct *up)
                local_irq_restore(flags);
 }
 
-struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid)
+struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid)
 {
        struct hlist_head *hashent = uidhashentry(ns, uid);
        struct user_struct *up, *new;
@@ -403,29 +399,15 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid)
        spin_unlock_irq(&uidhash_lock);
 
        if (!up) {
-               new = kmem_cache_alloc(uid_cachep, GFP_KERNEL);
+               new = kmem_cache_zalloc(uid_cachep, GFP_KERNEL);
                if (!new)
                        goto out_unlock;
 
                new->uid = uid;
                atomic_set(&new->__count, 1);
-               atomic_set(&new->processes, 0);
-               atomic_set(&new->files, 0);
-               atomic_set(&new->sigpending, 0);
-#ifdef CONFIG_INOTIFY_USER
-               atomic_set(&new->inotify_watches, 0);
-               atomic_set(&new->inotify_devs, 0);
-#endif
-#ifdef CONFIG_POSIX_MQUEUE
-               new->mq_bytes = 0;
-#endif
-               new->locked_shm = 0;
-
-               if (alloc_uid_keyring(new, current) < 0)
-                       goto out_free_user;
 
                if (sched_create_user(new) < 0)
-                       goto out_put_keys;
+                       goto out_free_user;
 
                if (uids_user_create(new))
                        goto out_destoy_sched;
@@ -459,9 +441,6 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid)
 
 out_destoy_sched:
        sched_destroy_user(new);
-out_put_keys:
-       key_put(new->uid_keyring);
-       key_put(new->session_keyring);
 out_free_user:
        kmem_cache_free(uid_cachep, new);
 out_unlock:
index 4c9006275df7fef80ae61944d39cdeea78246bb0..a9ab0596de44afe2bf3daa75c2c4ddca064c7f97 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/nsproxy.h>
+#include <linux/slab.h>
 #include <linux/user_namespace.h>
 
 /*
@@ -73,3 +74,4 @@ void free_user_ns(struct kref *kref)
        release_uids(ns);
        kfree(ns);
 }
+EXPORT_SYMBOL(free_user_ns);
index 816d7b24fa031af51b08d9108366d21626e3d38e..64d398f1244436cbdc4ede981dd927e39ee708b5 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/utsname.h>
 #include <linux/version.h>
 #include <linux/err.h>
+#include <linux/slab.h>
 
 /*
  * Clone a new ns copying an original utsname, setting refcount to 1
index 00ff4d08e370c4ee3e5d23cabb9c86b0e53f7833..721093a22561100bd626a9e16981c768ead6c40f 100644 (file)
@@ -158,8 +158,8 @@ static void __queue_work(struct cpu_workqueue_struct *cwq,
  *
  * Returns 0 if @work was already on a queue, non-zero otherwise.
  *
- * We queue the work to the CPU it was submitted, but there is no
- * guarantee that it will be processed by that CPU.
+ * We queue the work to the CPU on which it was submitted, but if the CPU dies
+ * it can be processed by another CPU.
  */
 int queue_work(struct workqueue_struct *wq, struct work_struct *work)
 {
@@ -247,7 +247,7 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq)
        if (cwq->run_depth > 3) {
                /* morton gets to eat his hat */
                printk("%s: recursion depth exceeded: %d\n",
-                       __FUNCTION__, cwq->run_depth);
+                       __func__, cwq->run_depth);
                dump_stack();
        }
        while (!list_empty(&cwq->worklist)) {
@@ -772,7 +772,7 @@ struct workqueue_struct *__create_workqueue_key(const char *name,
 }
 EXPORT_SYMBOL_GPL(__create_workqueue_key);
 
-static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu)
+static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq)
 {
        /*
         * Our caller is either destroy_workqueue() or CPU_DEAD,
@@ -808,19 +808,16 @@ static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu)
 void destroy_workqueue(struct workqueue_struct *wq)
 {
        const cpumask_t *cpu_map = wq_cpu_map(wq);
-       struct cpu_workqueue_struct *cwq;
        int cpu;
 
        get_online_cpus();
        spin_lock(&workqueue_lock);
        list_del(&wq->list);
        spin_unlock(&workqueue_lock);
-       put_online_cpus();
 
-       for_each_cpu_mask(cpu, *cpu_map) {
-               cwq = per_cpu_ptr(wq->cpu_wq, cpu);
-               cleanup_workqueue_thread(cwq, cpu);
-       }
+       for_each_cpu_mask(cpu, *cpu_map)
+               cleanup_workqueue_thread(per_cpu_ptr(wq->cpu_wq, cpu));
+       put_online_cpus();
 
        free_percpu(wq->cpu_wq);
        kfree(wq);
@@ -838,7 +835,6 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
        action &= ~CPU_TASKS_FROZEN;
 
        switch (action) {
-
        case CPU_UP_PREPARE:
                cpu_set(cpu, cpu_populated_map);
        }
@@ -861,11 +857,17 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
                case CPU_UP_CANCELED:
                        start_workqueue_thread(cwq, -1);
                case CPU_DEAD:
-                       cleanup_workqueue_thread(cwq, cpu);
+                       cleanup_workqueue_thread(cwq);
                        break;
                }
        }
 
+       switch (action) {
+       case CPU_UP_CANCELED:
+       case CPU_DEAD:
+               cpu_clear(cpu, cpu_populated_map);
+       }
+
        return NOTIFY_OK;
 }
 
index 754cc0027f2a8acc6f8358dd6a1ae0b1346845ba..d2099f41aa1ebe46bc614c7187290f7a32dd941c 100644 (file)
@@ -194,6 +194,37 @@ config TIMER_STATS
          (it defaults to deactivated on bootup and will only be activated
          if some application like powertop activates it explicitly).
 
+config DEBUG_OBJECTS
+       bool "Debug object operations"
+       depends on DEBUG_KERNEL
+       help
+         If you say Y here, additional code will be inserted into the
+         kernel to track the life time of various objects and validate
+         the operations on those objects.
+
+config DEBUG_OBJECTS_SELFTEST
+       bool "Debug objects selftest"
+       depends on DEBUG_OBJECTS
+       help
+         This enables the selftest of the object debug code.
+
+config DEBUG_OBJECTS_FREE
+       bool "Debug objects in freed memory"
+       depends on DEBUG_OBJECTS
+       help
+         This enables checks whether a k/v free operation frees an area
+         which contains an object which has not been deactivated
+         properly. This can make kmalloc/kfree-intensive workloads
+         much slower.
+
+config DEBUG_OBJECTS_TIMERS
+       bool "Debug timer objects"
+       depends on DEBUG_OBJECTS
+       help
+         If you say Y here, additional code will be inserted into the
+         timer routines to track the life time of timer objects and
+         validate the timer operations.
+
 config DEBUG_SLAB
        bool "Debug slab memory allocations"
        depends on DEBUG_KERNEL && SLAB
index 2d7001b7f5a4d641be0c618a6405d4c9863b41fb..74b0cfb1fcc3c0eb009648484a368116d0681f88 100644 (file)
@@ -6,7 +6,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
         rbtree.o radix-tree.o dump_stack.o \
         idr.o int_sqrt.o extable.o prio_tree.o \
         sha1.o irq_regs.o reciprocal_div.o argv_split.o \
-        proportions.o prio_heap.o
+        proportions.o prio_heap.o ratelimit.o
 
 lib-$(CONFIG_MMU) += ioremap.o
 lib-$(CONFIG_SMP) += cpumask.o
@@ -36,6 +36,7 @@ obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
 obj-$(CONFIG_PLIST) += plist.o
 obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
 obj-$(CONFIG_DEBUG_LIST) += list_debug.o
+obj-$(CONFIG_DEBUG_OBJECTS) += debugobjects.o
 
 ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
   lib-y += dec_and_lock.o
diff --git a/lib/debugobjects.c b/lib/debugobjects.c
new file mode 100644 (file)
index 0000000..a76a5e1
--- /dev/null
@@ -0,0 +1,890 @@
+/*
+ * Generic infrastructure for lifetime debugging of objects.
+ *
+ * Started by Thomas Gleixner
+ *
+ * Copyright (C) 2008, Thomas Gleixner <tglx@linutronix.de>
+ *
+ * For licencing details see kernel-base/COPYING
+ */
+#include <linux/debugobjects.h>
+#include <linux/interrupt.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/hash.h>
+
+#define ODEBUG_HASH_BITS       14
+#define ODEBUG_HASH_SIZE       (1 << ODEBUG_HASH_BITS)
+
+#define ODEBUG_POOL_SIZE       512
+#define ODEBUG_POOL_MIN_LEVEL  256
+
+#define ODEBUG_CHUNK_SHIFT     PAGE_SHIFT
+#define ODEBUG_CHUNK_SIZE      (1 << ODEBUG_CHUNK_SHIFT)
+#define ODEBUG_CHUNK_MASK      (~(ODEBUG_CHUNK_SIZE - 1))
+
+struct debug_bucket {
+       struct hlist_head       list;
+       spinlock_t              lock;
+};
+
+static struct debug_bucket     obj_hash[ODEBUG_HASH_SIZE];
+
+static struct debug_obj                obj_static_pool[ODEBUG_POOL_SIZE];
+
+static DEFINE_SPINLOCK(pool_lock);
+
+static HLIST_HEAD(obj_pool);
+
+static int                     obj_pool_min_free = ODEBUG_POOL_SIZE;
+static int                     obj_pool_free = ODEBUG_POOL_SIZE;
+static int                     obj_pool_used;
+static int                     obj_pool_max_used;
+static struct kmem_cache       *obj_cache;
+
+static int                     debug_objects_maxchain __read_mostly;
+static int                     debug_objects_fixups __read_mostly;
+static int                     debug_objects_warnings __read_mostly;
+static int                     debug_objects_enabled __read_mostly;
+static struct debug_obj_descr  *descr_test  __read_mostly;
+
+static int __init enable_object_debug(char *str)
+{
+       debug_objects_enabled = 1;
+       return 0;
+}
+early_param("debug_objects", enable_object_debug);
+
+static const char *obj_states[ODEBUG_STATE_MAX] = {
+       [ODEBUG_STATE_NONE]             = "none",
+       [ODEBUG_STATE_INIT]             = "initialized",
+       [ODEBUG_STATE_INACTIVE]         = "inactive",
+       [ODEBUG_STATE_ACTIVE]           = "active",
+       [ODEBUG_STATE_DESTROYED]        = "destroyed",
+       [ODEBUG_STATE_NOTAVAILABLE]     = "not available",
+};
+
+static int fill_pool(void)
+{
+       gfp_t gfp = GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN;
+       struct debug_obj *new;
+
+       if (likely(obj_pool_free >= ODEBUG_POOL_MIN_LEVEL))
+               return obj_pool_free;
+
+       if (unlikely(!obj_cache))
+               return obj_pool_free;
+
+       while (obj_pool_free < ODEBUG_POOL_MIN_LEVEL) {
+
+               new = kmem_cache_zalloc(obj_cache, gfp);
+               if (!new)
+                       return obj_pool_free;
+
+               spin_lock(&pool_lock);
+               hlist_add_head(&new->node, &obj_pool);
+               obj_pool_free++;
+               spin_unlock(&pool_lock);
+       }
+       return obj_pool_free;
+}
+
+/*
+ * Lookup an object in the hash bucket.
+ */
+static struct debug_obj *lookup_object(void *addr, struct debug_bucket *b)
+{
+       struct hlist_node *node;
+       struct debug_obj *obj;
+       int cnt = 0;
+
+       hlist_for_each_entry(obj, node, &b->list, node) {
+               cnt++;
+               if (obj->object == addr)
+                       return obj;
+       }
+       if (cnt > debug_objects_maxchain)
+               debug_objects_maxchain = cnt;
+
+       return NULL;
+}
+
+/*
+ * Allocate a new object. If the pool is empty and no refill possible,
+ * switch off the debugger.
+ */
+static struct debug_obj *
+alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr)
+{
+       struct debug_obj *obj = NULL;
+       int retry = 0;
+
+repeat:
+       spin_lock(&pool_lock);
+       if (obj_pool.first) {
+               obj         = hlist_entry(obj_pool.first, typeof(*obj), node);
+
+               obj->object = addr;
+               obj->descr  = descr;
+               obj->state  = ODEBUG_STATE_NONE;
+               hlist_del(&obj->node);
+
+               hlist_add_head(&obj->node, &b->list);
+
+               obj_pool_used++;
+               if (obj_pool_used > obj_pool_max_used)
+                       obj_pool_max_used = obj_pool_used;
+
+               obj_pool_free--;
+               if (obj_pool_free < obj_pool_min_free)
+                       obj_pool_min_free = obj_pool_free;
+       }
+       spin_unlock(&pool_lock);
+
+       if (fill_pool() && !obj && !retry++)
+               goto repeat;
+
+       return obj;
+}
+
+/*
+ * Put the object back into the pool or give it back to kmem_cache:
+ */
+static void free_object(struct debug_obj *obj)
+{
+       unsigned long idx = (unsigned long)(obj - obj_static_pool);
+
+       if (obj_pool_free < ODEBUG_POOL_SIZE || idx < ODEBUG_POOL_SIZE) {
+               spin_lock(&pool_lock);
+               hlist_add_head(&obj->node, &obj_pool);
+               obj_pool_free++;
+               obj_pool_used--;
+               spin_unlock(&pool_lock);
+       } else {
+               spin_lock(&pool_lock);
+               obj_pool_used--;
+               spin_unlock(&pool_lock);
+               kmem_cache_free(obj_cache, obj);
+       }
+}
+
+/*
+ * We run out of memory. That means we probably have tons of objects
+ * allocated.
+ */
+static void debug_objects_oom(void)
+{
+       struct debug_bucket *db = obj_hash;
+       struct hlist_node *node, *tmp;
+       struct debug_obj *obj;
+       unsigned long flags;
+       int i;
+
+       printk(KERN_WARNING "ODEBUG: Out of memory. ODEBUG disabled\n");
+
+       for (i = 0; i < ODEBUG_HASH_SIZE; i++, db++) {
+               spin_lock_irqsave(&db->lock, flags);
+               hlist_for_each_entry_safe(obj, node, tmp, &db->list, node) {
+                       hlist_del(&obj->node);
+                       free_object(obj);
+               }
+               spin_unlock_irqrestore(&db->lock, flags);
+       }
+}
+
+/*
+ * We use the pfn of the address for the hash. That way we can check
+ * for freed objects simply by checking the affected bucket.
+ */
+static struct debug_bucket *get_bucket(unsigned long addr)
+{
+       unsigned long hash;
+
+       hash = hash_long((addr >> ODEBUG_CHUNK_SHIFT), ODEBUG_HASH_BITS);
+       return &obj_hash[hash];
+}
+
+static void debug_print_object(struct debug_obj *obj, char *msg)
+{
+       static int limit;
+
+       if (limit < 5 && obj->descr != descr_test) {
+               limit++;
+               printk(KERN_ERR "ODEBUG: %s %s object type: %s\n", msg,
+                      obj_states[obj->state], obj->descr->name);
+               WARN_ON(1);
+       }
+       debug_objects_warnings++;
+}
+
+/*
+ * Try to repair the damage, so we have a better chance to get useful
+ * debug output.
+ */
+static void
+debug_object_fixup(int (*fixup)(void *addr, enum debug_obj_state state),
+                  void * addr, enum debug_obj_state state)
+{
+       if (fixup)
+               debug_objects_fixups += fixup(addr, state);
+}
+
+static void debug_object_is_on_stack(void *addr, int onstack)
+{
+       void *stack = current->stack;
+       int is_on_stack;
+       static int limit;
+
+       if (limit > 4)
+               return;
+
+       is_on_stack = (addr >= stack && addr < (stack + THREAD_SIZE));
+
+       if (is_on_stack == onstack)
+               return;
+
+       limit++;
+       if (is_on_stack)
+               printk(KERN_WARNING
+                      "ODEBUG: object is on stack, but not annotated\n");
+       else
+               printk(KERN_WARNING
+                      "ODEBUG: object is not on stack, but annotated\n");
+       WARN_ON(1);
+}
+
+static void
+__debug_object_init(void *addr, struct debug_obj_descr *descr, int onstack)
+{
+       enum debug_obj_state state;
+       struct debug_bucket *db;
+       struct debug_obj *obj;
+       unsigned long flags;
+
+       db = get_bucket((unsigned long) addr);
+
+       spin_lock_irqsave(&db->lock, flags);
+
+       obj = lookup_object(addr, db);
+       if (!obj) {
+               obj = alloc_object(addr, db, descr);
+               if (!obj) {
+                       debug_objects_enabled = 0;
+                       spin_unlock_irqrestore(&db->lock, flags);
+                       debug_objects_oom();
+                       return;
+               }
+               debug_object_is_on_stack(addr, onstack);
+       }
+
+       switch (obj->state) {
+       case ODEBUG_STATE_NONE:
+       case ODEBUG_STATE_INIT:
+       case ODEBUG_STATE_INACTIVE:
+               obj->state = ODEBUG_STATE_INIT;
+               break;
+
+       case ODEBUG_STATE_ACTIVE:
+               debug_print_object(obj, "init");
+               state = obj->state;
+               spin_unlock_irqrestore(&db->lock, flags);
+               debug_object_fixup(descr->fixup_init, addr, state);
+               return;
+
+       case ODEBUG_STATE_DESTROYED:
+               debug_print_object(obj, "init");
+               break;
+       default:
+               break;
+       }
+
+       spin_unlock_irqrestore(&db->lock, flags);
+}
+
+/**
+ * debug_object_init - debug checks when an object is initialized
+ * @addr:      address of the object
+ * @descr:     pointer to an object specific debug description structure
+ */
+void debug_object_init(void *addr, struct debug_obj_descr *descr)
+{
+       if (!debug_objects_enabled)
+               return;
+
+       __debug_object_init(addr, descr, 0);
+}
+
+/**
+ * debug_object_init_on_stack - debug checks when an object on stack is
+ *                             initialized
+ * @addr:      address of the object
+ * @descr:     pointer to an object specific debug description structure
+ */
+void debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr)
+{
+       if (!debug_objects_enabled)
+               return;
+
+       __debug_object_init(addr, descr, 1);
+}
+
+/**
+ * debug_object_activate - debug checks when an object is activated
+ * @addr:      address of the object
+ * @descr:     pointer to an object specific debug description structure
+ */
+void debug_object_activate(void *addr, struct debug_obj_descr *descr)
+{
+       enum debug_obj_state state;
+       struct debug_bucket *db;
+       struct debug_obj *obj;
+       unsigned long flags;
+
+       if (!debug_objects_enabled)
+               return;
+
+       db = get_bucket((unsigned long) addr);
+
+       spin_lock_irqsave(&db->lock, flags);
+
+       obj = lookup_object(addr, db);
+       if (obj) {
+               switch (obj->state) {
+               case ODEBUG_STATE_INIT:
+               case ODEBUG_STATE_INACTIVE:
+                       obj->state = ODEBUG_STATE_ACTIVE;
+                       break;
+
+               case ODEBUG_STATE_ACTIVE:
+                       debug_print_object(obj, "activate");
+                       state = obj->state;
+                       spin_unlock_irqrestore(&db->lock, flags);
+                       debug_object_fixup(descr->fixup_activate, addr, state);
+                       return;
+
+               case ODEBUG_STATE_DESTROYED:
+                       debug_print_object(obj, "activate");
+                       break;
+               default:
+                       break;
+               }
+               spin_unlock_irqrestore(&db->lock, flags);
+               return;
+       }
+
+       spin_unlock_irqrestore(&db->lock, flags);
+       /*
+        * This happens when a static object is activated. We
+        * let the type specific code decide whether this is
+        * true or not.
+        */
+       debug_object_fixup(descr->fixup_activate, addr,
+                          ODEBUG_STATE_NOTAVAILABLE);
+}
+
+/**
+ * debug_object_deactivate - debug checks when an object is deactivated
+ * @addr:      address of the object
+ * @descr:     pointer to an object specific debug description structure
+ */
+void debug_object_deactivate(void *addr, struct debug_obj_descr *descr)
+{
+       struct debug_bucket *db;
+       struct debug_obj *obj;
+       unsigned long flags;
+
+       if (!debug_objects_enabled)
+               return;
+
+       db = get_bucket((unsigned long) addr);
+
+       spin_lock_irqsave(&db->lock, flags);
+
+       obj = lookup_object(addr, db);
+       if (obj) {
+               switch (obj->state) {
+               case ODEBUG_STATE_INIT:
+               case ODEBUG_STATE_INACTIVE:
+               case ODEBUG_STATE_ACTIVE:
+                       obj->state = ODEBUG_STATE_INACTIVE;
+                       break;
+
+               case ODEBUG_STATE_DESTROYED:
+                       debug_print_object(obj, "deactivate");
+                       break;
+               default:
+                       break;
+               }
+       } else {
+               struct debug_obj o = { .object = addr,
+                                      .state = ODEBUG_STATE_NOTAVAILABLE,
+                                      .descr = descr };
+
+               debug_print_object(&o, "deactivate");
+       }
+
+       spin_unlock_irqrestore(&db->lock, flags);
+}
+
+/**
+ * debug_object_destroy - debug checks when an object is destroyed
+ * @addr:      address of the object
+ * @descr:     pointer to an object specific debug description structure
+ */
+void debug_object_destroy(void *addr, struct debug_obj_descr *descr)
+{
+       enum debug_obj_state state;
+       struct debug_bucket *db;
+       struct debug_obj *obj;
+       unsigned long flags;
+
+       if (!debug_objects_enabled)
+               return;
+
+       db = get_bucket((unsigned long) addr);
+
+       spin_lock_irqsave(&db->lock, flags);
+
+       obj = lookup_object(addr, db);
+       if (!obj)
+               goto out_unlock;
+
+       switch (obj->state) {
+       case ODEBUG_STATE_NONE:
+       case ODEBUG_STATE_INIT:
+       case ODEBUG_STATE_INACTIVE:
+               obj->state = ODEBUG_STATE_DESTROYED;
+               break;
+       case ODEBUG_STATE_ACTIVE:
+               debug_print_object(obj, "destroy");
+               state = obj->state;
+               spin_unlock_irqrestore(&db->lock, flags);
+               debug_object_fixup(descr->fixup_destroy, addr, state);
+               return;
+
+       case ODEBUG_STATE_DESTROYED:
+               debug_print_object(obj, "destroy");
+               break;
+       default:
+               break;
+       }
+out_unlock:
+       spin_unlock_irqrestore(&db->lock, flags);
+}
+
+/**
+ * debug_object_free - debug checks when an object is freed
+ * @addr:      address of the object
+ * @descr:     pointer to an object specific debug description structure
+ */
+void debug_object_free(void *addr, struct debug_obj_descr *descr)
+{
+       enum debug_obj_state state;
+       struct debug_bucket *db;
+       struct debug_obj *obj;
+       unsigned long flags;
+
+       if (!debug_objects_enabled)
+               return;
+
+       db = get_bucket((unsigned long) addr);
+
+       spin_lock_irqsave(&db->lock, flags);
+
+       obj = lookup_object(addr, db);
+       if (!obj)
+               goto out_unlock;
+
+       switch (obj->state) {
+       case ODEBUG_STATE_ACTIVE:
+               debug_print_object(obj, "free");
+               state = obj->state;
+               spin_unlock_irqrestore(&db->lock, flags);
+               debug_object_fixup(descr->fixup_free, addr, state);
+               return;
+       default:
+               hlist_del(&obj->node);
+               free_object(obj);
+               break;
+       }
+out_unlock:
+       spin_unlock_irqrestore(&db->lock, flags);
+}
+
+#ifdef CONFIG_DEBUG_OBJECTS_FREE
+static void __debug_check_no_obj_freed(const void *address, unsigned long size)
+{
+       unsigned long flags, oaddr, saddr, eaddr, paddr, chunks;
+       struct hlist_node *node, *tmp;
+       struct debug_obj_descr *descr;
+       enum debug_obj_state state;
+       struct debug_bucket *db;
+       struct debug_obj *obj;
+       int cnt;
+
+       saddr = (unsigned long) address;
+       eaddr = saddr + size;
+       paddr = saddr & ODEBUG_CHUNK_MASK;
+       chunks = ((eaddr - paddr) + (ODEBUG_CHUNK_SIZE - 1));
+       chunks >>= ODEBUG_CHUNK_SHIFT;
+
+       for (;chunks > 0; chunks--, paddr += ODEBUG_CHUNK_SIZE) {
+               db = get_bucket(paddr);
+
+repeat:
+               cnt = 0;
+               spin_lock_irqsave(&db->lock, flags);
+               hlist_for_each_entry_safe(obj, node, tmp, &db->list, node) {
+                       cnt++;
+                       oaddr = (unsigned long) obj->object;
+                       if (oaddr < saddr || oaddr >= eaddr)
+                               continue;
+
+                       switch (obj->state) {
+                       case ODEBUG_STATE_ACTIVE:
+                               debug_print_object(obj, "free");
+                               descr = obj->descr;
+                               state = obj->state;
+                               spin_unlock_irqrestore(&db->lock, flags);
+                               debug_object_fixup(descr->fixup_free,
+                                                  (void *) oaddr, state);
+                               goto repeat;
+                       default:
+                               hlist_del(&obj->node);
+                               free_object(obj);
+                               break;
+                       }
+               }
+               spin_unlock_irqrestore(&db->lock, flags);
+               if (cnt > debug_objects_maxchain)
+                       debug_objects_maxchain = cnt;
+       }
+}
+
+void debug_check_no_obj_freed(const void *address, unsigned long size)
+{
+       if (debug_objects_enabled)
+               __debug_check_no_obj_freed(address, size);
+}
+#endif
+
+#ifdef CONFIG_DEBUG_FS
+
+static int debug_stats_show(struct seq_file *m, void *v)
+{
+       seq_printf(m, "max_chain     :%d\n", debug_objects_maxchain);
+       seq_printf(m, "warnings      :%d\n", debug_objects_warnings);
+       seq_printf(m, "fixups        :%d\n", debug_objects_fixups);
+       seq_printf(m, "pool_free     :%d\n", obj_pool_free);
+       seq_printf(m, "pool_min_free :%d\n", obj_pool_min_free);
+       seq_printf(m, "pool_used     :%d\n", obj_pool_used);
+       seq_printf(m, "pool_max_used :%d\n", obj_pool_max_used);
+       return 0;
+}
+
+static int debug_stats_open(struct inode *inode, struct file *filp)
+{
+       return single_open(filp, debug_stats_show, NULL);
+}
+
+static const struct file_operations debug_stats_fops = {
+       .open           = debug_stats_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int __init debug_objects_init_debugfs(void)
+{
+       struct dentry *dbgdir, *dbgstats;
+
+       if (!debug_objects_enabled)
+               return 0;
+
+       dbgdir = debugfs_create_dir("debug_objects", NULL);
+       if (!dbgdir)
+               return -ENOMEM;
+
+       dbgstats = debugfs_create_file("stats", 0444, dbgdir, NULL,
+                                      &debug_stats_fops);
+       if (!dbgstats)
+               goto err;
+
+       return 0;
+
+err:
+       debugfs_remove(dbgdir);
+
+       return -ENOMEM;
+}
+__initcall(debug_objects_init_debugfs);
+
+#else
+static inline void debug_objects_init_debugfs(void) { }
+#endif
+
+#ifdef CONFIG_DEBUG_OBJECTS_SELFTEST
+
+/* Random data structure for the self test */
+struct self_test {
+       unsigned long   dummy1[6];
+       int             static_init;
+       unsigned long   dummy2[3];
+};
+
+static __initdata struct debug_obj_descr descr_type_test;
+
+/*
+ * fixup_init is called when:
+ * - an active object is initialized
+ */
+static int __init fixup_init(void *addr, enum debug_obj_state state)
+{
+       struct self_test *obj = addr;
+
+       switch (state) {
+       case ODEBUG_STATE_ACTIVE:
+               debug_object_deactivate(obj, &descr_type_test);
+               debug_object_init(obj, &descr_type_test);
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+/*
+ * fixup_activate is called when:
+ * - an active object is activated
+ * - an unknown object is activated (might be a statically initialized object)
+ */
+static int __init fixup_activate(void *addr, enum debug_obj_state state)
+{
+       struct self_test *obj = addr;
+
+       switch (state) {
+       case ODEBUG_STATE_NOTAVAILABLE:
+               if (obj->static_init == 1) {
+                       debug_object_init(obj, &descr_type_test);
+                       debug_object_activate(obj, &descr_type_test);
+                       /*
+                        * Real code should return 0 here ! This is
+                        * not a fixup of some bad behaviour. We
+                        * merily call the debug_init function to keep
+                        * track of the object.
+                        */
+                       return 1;
+               } else {
+                       /* Real code needs to emit a warning here */
+               }
+               return 0;
+
+       case ODEBUG_STATE_ACTIVE:
+               debug_object_deactivate(obj, &descr_type_test);
+               debug_object_activate(obj, &descr_type_test);
+               return 1;
+
+       default:
+               return 0;
+       }
+}
+
+/*
+ * fixup_destroy is called when:
+ * - an active object is destroyed
+ */
+static int __init fixup_destroy(void *addr, enum debug_obj_state state)
+{
+       struct self_test *obj = addr;
+
+       switch (state) {
+       case ODEBUG_STATE_ACTIVE:
+               debug_object_deactivate(obj, &descr_type_test);
+               debug_object_destroy(obj, &descr_type_test);
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+/*
+ * fixup_free is called when:
+ * - an active object is freed
+ */
+static int __init fixup_free(void *addr, enum debug_obj_state state)
+{
+       struct self_test *obj = addr;
+
+       switch (state) {
+       case ODEBUG_STATE_ACTIVE:
+               debug_object_deactivate(obj, &descr_type_test);
+               debug_object_free(obj, &descr_type_test);
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static int
+check_results(void *addr, enum debug_obj_state state, int fixups, int warnings)
+{
+       struct debug_bucket *db;
+       struct debug_obj *obj;
+       unsigned long flags;
+       int res = -EINVAL;
+
+       db = get_bucket((unsigned long) addr);
+
+       spin_lock_irqsave(&db->lock, flags);
+
+       obj = lookup_object(addr, db);
+       if (!obj && state != ODEBUG_STATE_NONE) {
+               printk(KERN_ERR "ODEBUG: selftest object not found\n");
+               WARN_ON(1);
+               goto out;
+       }
+       if (obj && obj->state != state) {
+               printk(KERN_ERR "ODEBUG: selftest wrong state: %d != %d\n",
+                      obj->state, state);
+               WARN_ON(1);
+               goto out;
+       }
+       if (fixups != debug_objects_fixups) {
+               printk(KERN_ERR "ODEBUG: selftest fixups failed %d != %d\n",
+                      fixups, debug_objects_fixups);
+               WARN_ON(1);
+               goto out;
+       }
+       if (warnings != debug_objects_warnings) {
+               printk(KERN_ERR "ODEBUG: selftest warnings failed %d != %d\n",
+                      warnings, debug_objects_warnings);
+               WARN_ON(1);
+               goto out;
+       }
+       res = 0;
+out:
+       spin_unlock_irqrestore(&db->lock, flags);
+       if (res)
+               debug_objects_enabled = 0;
+       return res;
+}
+
+static __initdata struct debug_obj_descr descr_type_test = {
+       .name                   = "selftest",
+       .fixup_init             = fixup_init,
+       .fixup_activate         = fixup_activate,
+       .fixup_destroy          = fixup_destroy,
+       .fixup_free             = fixup_free,
+};
+
+static __initdata struct self_test obj = { .static_init = 0 };
+
+static void __init debug_objects_selftest(void)
+{
+       int fixups, oldfixups, warnings, oldwarnings;
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       fixups = oldfixups = debug_objects_fixups;
+       warnings = oldwarnings = debug_objects_warnings;
+       descr_test = &descr_type_test;
+
+       debug_object_init(&obj, &descr_type_test);
+       if (check_results(&obj, ODEBUG_STATE_INIT, fixups, warnings))
+               goto out;
+       debug_object_activate(&obj, &descr_type_test);
+       if (check_results(&obj, ODEBUG_STATE_ACTIVE, fixups, warnings))
+               goto out;
+       debug_object_activate(&obj, &descr_type_test);
+       if (check_results(&obj, ODEBUG_STATE_ACTIVE, ++fixups, ++warnings))
+               goto out;
+       debug_object_deactivate(&obj, &descr_type_test);
+       if (check_results(&obj, ODEBUG_STATE_INACTIVE, fixups, warnings))
+               goto out;
+       debug_object_destroy(&obj, &descr_type_test);
+       if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, warnings))
+               goto out;
+       debug_object_init(&obj, &descr_type_test);
+       if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, ++warnings))
+               goto out;
+       debug_object_activate(&obj, &descr_type_test);
+       if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, ++warnings))
+               goto out;
+       debug_object_deactivate(&obj, &descr_type_test);
+       if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, ++warnings))
+               goto out;
+       debug_object_free(&obj, &descr_type_test);
+       if (check_results(&obj, ODEBUG_STATE_NONE, fixups, warnings))
+               goto out;
+
+       obj.static_init = 1;
+       debug_object_activate(&obj, &descr_type_test);
+       if (check_results(&obj, ODEBUG_STATE_ACTIVE, ++fixups, warnings))
+               goto out;
+       debug_object_init(&obj, &descr_type_test);
+       if (check_results(&obj, ODEBUG_STATE_INIT, ++fixups, ++warnings))
+               goto out;
+       debug_object_free(&obj, &descr_type_test);
+       if (check_results(&obj, ODEBUG_STATE_NONE, fixups, warnings))
+               goto out;
+
+#ifdef CONFIG_DEBUG_OBJECTS_FREE
+       debug_object_init(&obj, &descr_type_test);
+       if (check_results(&obj, ODEBUG_STATE_INIT, fixups, warnings))
+               goto out;
+       debug_object_activate(&obj, &descr_type_test);
+       if (check_results(&obj, ODEBUG_STATE_ACTIVE, fixups, warnings))
+               goto out;
+       __debug_check_no_obj_freed(&obj, sizeof(obj));
+       if (check_results(&obj, ODEBUG_STATE_NONE, ++fixups, ++warnings))
+               goto out;
+#endif
+       printk(KERN_INFO "ODEBUG: selftest passed\n");
+
+out:
+       debug_objects_fixups = oldfixups;
+       debug_objects_warnings = oldwarnings;
+       descr_test = NULL;
+
+       local_irq_restore(flags);
+}
+#else
+static inline void debug_objects_selftest(void) { }
+#endif
+
+/*
+ * Called during early boot to initialize the hash buckets and link
+ * the static object pool objects into the poll list. After this call
+ * the object tracker is fully operational.
+ */
+void __init debug_objects_early_init(void)
+{
+       int i;
+
+       for (i = 0; i < ODEBUG_HASH_SIZE; i++)
+               spin_lock_init(&obj_hash[i].lock);
+
+       for (i = 0; i < ODEBUG_POOL_SIZE; i++)
+               hlist_add_head(&obj_static_pool[i].node, &obj_pool);
+}
+
+/*
+ * Called after the kmem_caches are functional to setup a dedicated
+ * cache pool, which has the SLAB_DEBUG_OBJECTS flag set. This flag
+ * prevents that the debug code is called on kmem_cache_free() for the
+ * debug tracker objects to avoid recursive calls.
+ */
+void __init debug_objects_mem_init(void)
+{
+       if (!debug_objects_enabled)
+               return;
+
+       obj_cache = kmem_cache_create("debug_objects_cache",
+                                     sizeof (struct debug_obj), 0,
+                                     SLAB_DEBUG_OBJECTS, NULL);
+
+       if (!obj_cache)
+               debug_objects_enabled = 0;
+       else
+               debug_objects_selftest();
+}
index d3f5784807b45a00fa2301727951f6fb3e325f35..24c59ded47a05d5617e2fe2501077f990de1ec4b 100644 (file)
@@ -20,8 +20,8 @@
 /*
  * Find the next set bit in a memory region.
  */
-unsigned long __find_next_bit(const unsigned long *addr,
-               unsigned long size, unsigned long offset)
+unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
+                           unsigned long offset)
 {
        const unsigned long *p = addr + BITOP_WORD(offset);
        unsigned long result = offset & ~(BITS_PER_LONG-1);
@@ -58,14 +58,14 @@ found_first:
 found_middle:
        return result + __ffs(tmp);
 }
-EXPORT_SYMBOL(__find_next_bit);
+EXPORT_SYMBOL(find_next_bit);
 
 /*
  * This implementation of find_{first,next}_zero_bit was stolen from
  * Linus' asm-alpha/bitops.h.
  */
-unsigned long __find_next_zero_bit(const unsigned long *addr,
-               unsigned long size, unsigned long offset)
+unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
+                                unsigned long offset)
 {
        const unsigned long *p = addr + BITOP_WORD(offset);
        unsigned long result = offset & ~(BITS_PER_LONG-1);
@@ -102,15 +102,14 @@ found_first:
 found_middle:
        return result + ffz(tmp);
 }
-EXPORT_SYMBOL(__find_next_zero_bit);
+EXPORT_SYMBOL(find_next_zero_bit);
 #endif /* CONFIG_GENERIC_FIND_NEXT_BIT */
 
 #ifdef CONFIG_GENERIC_FIND_FIRST_BIT
 /*
  * Find the first set bit in a memory region.
  */
-unsigned long __find_first_bit(const unsigned long *addr,
-               unsigned long size)
+unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
 {
        const unsigned long *p = addr;
        unsigned long result = 0;
@@ -131,13 +130,12 @@ unsigned long __find_first_bit(const unsigned long *addr,
 found:
        return result + __ffs(tmp);
 }
-EXPORT_SYMBOL(__find_first_bit);
+EXPORT_SYMBOL(find_first_bit);
 
 /*
  * Find the first cleared bit in a memory region.
  */
-unsigned long __find_first_zero_bit(const unsigned long *addr,
-               unsigned long size)
+unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size)
 {
        const unsigned long *p = addr;
        unsigned long result = 0;
@@ -158,7 +156,7 @@ unsigned long __find_first_zero_bit(const unsigned long *addr,
 found:
        return result + ffz(tmp);
 }
-EXPORT_SYMBOL(__find_first_zero_bit);
+EXPORT_SYMBOL(find_first_zero_bit);
 #endif /* CONFIG_GENERIC_FIND_FIRST_BIT */
 
 #ifdef __BIG_ENDIAN
index afbb0b1023d46cd5a3619175730c7ced7bc1e419..8368c81fcb7d21cd3d85c8c0880f918b9c1911f5 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -585,12 +585,11 @@ static void idr_cache_ctor(struct kmem_cache *idr_layer_cache, void *idr_layer)
        memset(idr_layer, 0, sizeof(struct idr_layer));
 }
 
-static  int init_id_cache(void)
+void __init idr_init_cache(void)
 {
-       if (!idr_layer_cache)
-               idr_layer_cache = kmem_cache_create("idr_layer_cache",
-                       sizeof(struct idr_layer), 0, 0, idr_cache_ctor);
-       return 0;
+       idr_layer_cache = kmem_cache_create("idr_layer_cache",
+                               sizeof(struct idr_layer), 0, SLAB_PANIC,
+                               idr_cache_ctor);
 }
 
 /**
@@ -602,7 +601,6 @@ static  int init_id_cache(void)
  */
 void idr_init(struct idr *idp)
 {
-       init_id_cache();
        memset(idp, 0, sizeof(struct idr));
        spin_lock_init(&idp->lock);
 }
index 845f91d3ac1226ad6bee1e87e1fc74169ccd36cf..9762294be06257b6d6e6873dbd6b0503f21029c1 100644 (file)
@@ -811,6 +811,9 @@ DEBG("<dyn");
   ll = malloc(sizeof(*ll) * (286+30));  /* literal/length and distance code lengths */
 #endif
 
+  if (ll == NULL)
+    return 1;
+
   /* make local bit buffer */
   b = bb;
   k = bk;
index dd6ca48fe6b0675267e9591267c2af876f3454c8..37a3ea4cac9f1c0a35c3e73430a5b28814f28d82 100644 (file)
@@ -257,7 +257,7 @@ EXPORT_SYMBOL(ioport_unmap);
 void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
 {
        resource_size_t start = pci_resource_start(dev, bar);
-       unsigned long len = pci_resource_len(dev, bar);
+       resource_size_t len = pci_resource_len(dev, bar);
        unsigned long flags = pci_resource_flags(dev, bar);
 
        if (!len || !start)
index 2c6490370922ccddf939db20e6bf0b71fcbf9526..fd78740321639afdf10438ed1890a5a61be15c18 100644 (file)
@@ -90,7 +90,7 @@ static void fill_kobj_path(struct kobject *kobj, char *path, int length)
        }
 
        pr_debug("kobject: '%s' (%p): %s: path = '%s'\n", kobject_name(kobj),
-                kobj, __FUNCTION__, path);
+                kobj, __func__, path);
 }
 
 /**
@@ -181,7 +181,7 @@ static int kobject_add_internal(struct kobject *kobj)
        }
 
        pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s'\n",
-                kobject_name(kobj), kobj, __FUNCTION__,
+                kobject_name(kobj), kobj, __func__,
                 parent ? kobject_name(parent) : "<NULL>",
                 kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>");
 
@@ -196,10 +196,10 @@ static int kobject_add_internal(struct kobject *kobj)
                        printk(KERN_ERR "%s failed for %s with "
                               "-EEXIST, don't try to register things with "
                               "the same name in the same directory.\n",
-                              __FUNCTION__, kobject_name(kobj));
+                              __func__, kobject_name(kobj));
                else
                        printk(KERN_ERR "%s failed for %s (%d)\n",
-                              __FUNCTION__, kobject_name(kobj), error);
+                              __func__, kobject_name(kobj), error);
                dump_stack();
        } else
                kobj->state_in_sysfs = 1;
@@ -540,7 +540,7 @@ static void kobject_cleanup(struct kobject *kobj)
        const char *name = kobj->name;
 
        pr_debug("kobject: '%s' (%p): %s\n",
-                kobject_name(kobj), kobj, __FUNCTION__);
+                kobject_name(kobj), kobj, __func__);
 
        if (t && !t->release)
                pr_debug("kobject: '%s' (%p): does not have a release() "
@@ -600,7 +600,7 @@ void kobject_put(struct kobject *kobj)
 
 static void dynamic_kobj_release(struct kobject *kobj)
 {
-       pr_debug("kobject: (%p): %s\n", kobj, __FUNCTION__);
+       pr_debug("kobject: (%p): %s\n", kobj, __func__);
        kfree(kobj);
 }
 
@@ -657,7 +657,7 @@ struct kobject *kobject_create_and_add(const char *name, struct kobject *parent)
        retval = kobject_add(kobj, parent, "%s", name);
        if (retval) {
                printk(KERN_WARNING "%s: kobject_add error: %d\n",
-                      __FUNCTION__, retval);
+                      __func__, retval);
                kobject_put(kobj);
                kobj = NULL;
        }
@@ -765,7 +765,7 @@ static void kset_release(struct kobject *kobj)
 {
        struct kset *kset = container_of(kobj, struct kset, kobj);
        pr_debug("kobject: '%s' (%p): %s\n",
-                kobject_name(kobj), kobj, __FUNCTION__);
+                kobject_name(kobj), kobj, __func__);
        kfree(kset);
 }
 
index 9fb6b86cf6b15970ede185e8233a975dd4049d8a..2fa545a631607dc1d0498a7c2bff592ad7d115bb 100644 (file)
@@ -101,7 +101,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
        int retval = 0;
 
        pr_debug("kobject: '%s' (%p): %s\n",
-                kobject_name(kobj), kobj, __FUNCTION__);
+                kobject_name(kobj), kobj, __func__);
 
        /* search the kset we belong to */
        top_kobj = kobj;
@@ -111,7 +111,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
        if (!top_kobj->kset) {
                pr_debug("kobject: '%s' (%p): %s: attempted to send uevent "
                         "without kset!\n", kobject_name(kobj), kobj,
-                        __FUNCTION__);
+                        __func__);
                return -EINVAL;
        }
 
@@ -123,7 +123,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
                if (!uevent_ops->filter(kset, kobj)) {
                        pr_debug("kobject: '%s' (%p): %s: filter function "
                                 "caused the event to drop!\n",
-                                kobject_name(kobj), kobj, __FUNCTION__);
+                                kobject_name(kobj), kobj, __func__);
                        return 0;
                }
 
@@ -135,7 +135,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
        if (!subsystem) {
                pr_debug("kobject: '%s' (%p): %s: unset subsystem caused the "
                         "event to drop!\n", kobject_name(kobj), kobj,
-                        __FUNCTION__);
+                        __func__);
                return 0;
        }
 
@@ -177,7 +177,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
                if (retval) {
                        pr_debug("kobject: '%s' (%p): %s: uevent() returned "
                                 "%d\n", kobject_name(kobj), kobj,
-                                __FUNCTION__, retval);
+                                __func__, retval);
                        goto exit;
                }
        }
index 393a0e915c23b252b747c62645beb463e25843ed..119174494cb5c096eaf5b1da239dbd5a4040ebc0 100644 (file)
@@ -102,6 +102,7 @@ void percpu_counter_destroy(struct percpu_counter *fbc)
                return;
 
        free_percpu(fbc->counters);
+       fbc->counters = NULL;
 #ifdef CONFIG_HOTPLUG_CPU
        mutex_lock(&percpu_counters_lock);
        list_del(&fbc->list);
index 9508d9a7af3ef9ba482925a9d1cdc34ef2fddd0e..4f387a643d723c3853bec845ef0a90018a0e00f0 100644 (file)
 #include <linux/proportions.h>
 #include <linux/rcupdate.h>
 
-/*
- * Limit the time part in order to ensure there are some bits left for the
- * cycle counter.
- */
-#define PROP_MAX_SHIFT (3*BITS_PER_LONG/4)
-
 int prop_descriptor_init(struct prop_descriptor *pd, int shift)
 {
        int err;
@@ -267,6 +261,38 @@ void __prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl)
        prop_put_global(pd, pg);
 }
 
+/*
+ * identical to __prop_inc_percpu, except that it limits this pl's fraction to
+ * @frac/PROP_FRAC_BASE by ignoring events when this limit has been exceeded.
+ */
+void __prop_inc_percpu_max(struct prop_descriptor *pd,
+                          struct prop_local_percpu *pl, long frac)
+{
+       struct prop_global *pg = prop_get_global(pd);
+
+       prop_norm_percpu(pg, pl);
+
+       if (unlikely(frac != PROP_FRAC_BASE)) {
+               unsigned long period_2 = 1UL << (pg->shift - 1);
+               unsigned long counter_mask = period_2 - 1;
+               unsigned long global_count;
+               long numerator, denominator;
+
+               numerator = percpu_counter_read_positive(&pl->events);
+               global_count = percpu_counter_read(&pg->events);
+               denominator = period_2 + (global_count & counter_mask);
+
+               if (numerator > ((denominator * frac) >> PROP_FRAC_SHIFT))
+                       goto out_put;
+       }
+
+       percpu_counter_add(&pl->events, 1);
+       percpu_counter_add(&pg->events, 1);
+
+out_put:
+       prop_put_global(pd, pg);
+}
+
 /*
  * Obtain a fraction of this proportion
  *
diff --git a/lib/ratelimit.c b/lib/ratelimit.c
new file mode 100644 (file)
index 0000000..485e304
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * ratelimit.c - Do something with rate limit.
+ *
+ * Isolated from kernel/printk.c by Dave Young <hidave.darkstar@gmail.com>
+ *
+ * This file is released under the GPLv2.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+
+/*
+ * __ratelimit - rate limiting
+ * @ratelimit_jiffies: minimum time in jiffies between two callbacks
+ * @ratelimit_burst: number of callbacks we do before ratelimiting
+ *
+ * This enforces a rate limit: not more than @ratelimit_burst callbacks
+ * in every ratelimit_jiffies
+ */
+int __ratelimit(int ratelimit_jiffies, int ratelimit_burst)
+{
+       static DEFINE_SPINLOCK(ratelimit_lock);
+       static unsigned toks = 10 * 5 * HZ;
+       static unsigned long last_msg;
+       static int missed;
+       unsigned long flags;
+       unsigned long now = jiffies;
+
+       spin_lock_irqsave(&ratelimit_lock, flags);
+       toks += now - last_msg;
+       last_msg = now;
+       if (toks > (ratelimit_burst * ratelimit_jiffies))
+               toks = ratelimit_burst * ratelimit_jiffies;
+       if (toks >= ratelimit_jiffies) {
+               int lost = missed;
+
+               missed = 0;
+               toks -= ratelimit_jiffies;
+               spin_unlock_irqrestore(&ratelimit_lock, flags);
+               if (lost)
+                       printk(KERN_WARNING "%s: %d messages suppressed\n",
+                               __func__, lost);
+               return 1;
+       }
+       missed++;
+       spin_unlock_irqrestore(&ratelimit_lock, flags);
+       return 0;
+}
+EXPORT_SYMBOL(__ratelimit);
index 025922807e6e648bb7dc4eda61bfd8fa609a221c..d568894df8ccd335c4acdcb47da4a7b3c4830150 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <linux/init.h>
 #include <linux/bootmem.h>
+#include <linux/iommu-helper.h>
 
 #define OFFSET(val,align) ((unsigned long)     \
                           ( (val) & ( (align) - 1)))
@@ -282,15 +283,6 @@ address_needs_mapping(struct device *hwdev, dma_addr_t addr)
        return (addr & ~mask) != 0;
 }
 
-static inline unsigned int is_span_boundary(unsigned int index,
-                                           unsigned int nslots,
-                                           unsigned long offset_slots,
-                                           unsigned long max_slots)
-{
-       unsigned long offset = (offset_slots + index) & (max_slots - 1);
-       return offset + nslots > max_slots;
-}
-
 /*
  * Allocates bounce buffer and returns its kernel virtual address.
  */
@@ -331,56 +323,53 @@ map_single(struct device *hwdev, char *buffer, size_t size, int dir)
         * request and allocate a buffer from that IO TLB pool.
         */
        spin_lock_irqsave(&io_tlb_lock, flags);
-       {
-               index = ALIGN(io_tlb_index, stride);
-               if (index >= io_tlb_nslabs)
-                       index = 0;
-               wrap = index;
-
-               do {
-                       while (is_span_boundary(index, nslots, offset_slots,
-                                               max_slots)) {
-                               index += stride;
-                               if (index >= io_tlb_nslabs)
-                                       index = 0;
-                               if (index == wrap)
-                                       goto not_found;
-                       }
-
-                       /*
-                        * If we find a slot that indicates we have 'nslots'
-                        * number of contiguous buffers, we allocate the
-                        * buffers from that slot and mark the entries as '0'
-                        * indicating unavailable.
-                        */
-                       if (io_tlb_list[index] >= nslots) {
-                               int count = 0;
-
-                               for (i = index; i < (int) (index + nslots); i++)
-                                       io_tlb_list[i] = 0;
-                               for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE -1) && io_tlb_list[i]; i--)
-                                       io_tlb_list[i] = ++count;
-                               dma_addr = io_tlb_start + (index << IO_TLB_SHIFT);
-
-                               /*
-                                * Update the indices to avoid searching in
-                                * the next round.
-                                */
-                               io_tlb_index = ((index + nslots) < io_tlb_nslabs
-                                               ? (index + nslots) : 0);
-
-                               goto found;
-                       }
+       index = ALIGN(io_tlb_index, stride);
+       if (index >= io_tlb_nslabs)
+               index = 0;
+       wrap = index;
+
+       do {
+               while (iommu_is_span_boundary(index, nslots, offset_slots,
+                                             max_slots)) {
                        index += stride;
                        if (index >= io_tlb_nslabs)
                                index = 0;
-               } while (index != wrap);
+                       if (index == wrap)
+                               goto not_found;
+               }
 
-  not_found:
-               spin_unlock_irqrestore(&io_tlb_lock, flags);
-               return NULL;
-       }
-  found:
+               /*
+                * If we find a slot that indicates we have 'nslots' number of
+                * contiguous buffers, we allocate the buffers from that slot
+                * and mark the entries as '0' indicating unavailable.
+                */
+               if (io_tlb_list[index] >= nslots) {
+                       int count = 0;
+
+                       for (i = index; i < (int) (index + nslots); i++)
+                               io_tlb_list[i] = 0;
+                       for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE - 1) && io_tlb_list[i]; i--)
+                               io_tlb_list[i] = ++count;
+                       dma_addr = io_tlb_start + (index << IO_TLB_SHIFT);
+
+                       /*
+                        * Update the indices to avoid searching in the next
+                        * round.
+                        */
+                       io_tlb_index = ((index + nslots) < io_tlb_nslabs
+                                       ? (index + nslots) : 0);
+
+                       goto found;
+               }
+               index += stride;
+               if (index >= io_tlb_nslabs)
+                       index = 0;
+       } while (index != wrap);
+
+not_found:
+       spin_unlock_irqrestore(&io_tlb_lock, flags);
+       return NULL;
+found:
        spin_unlock_irqrestore(&io_tlb_lock, flags);
 
        /*
@@ -566,7 +555,8 @@ swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
  * either swiotlb_unmap_single or swiotlb_dma_sync_single is performed.
  */
 dma_addr_t
-swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir)
+swiotlb_map_single_attrs(struct device *hwdev, void *ptr, size_t size,
+                        int dir, struct dma_attrs *attrs)
 {
        dma_addr_t dev_addr = virt_to_bus(ptr);
        void *map;
@@ -599,6 +589,13 @@ swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir)
 
        return dev_addr;
 }
+EXPORT_SYMBOL(swiotlb_map_single_attrs);
+
+dma_addr_t
+swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir)
+{
+       return swiotlb_map_single_attrs(hwdev, ptr, size, dir, NULL);
+}
 
 /*
  * Unmap a single streaming mode DMA translation.  The dma_addr and size must
@@ -609,8 +606,8 @@ swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir)
  * whatever the device wrote there.
  */
 void
-swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, size_t size,
-                    int dir)
+swiotlb_unmap_single_attrs(struct device *hwdev, dma_addr_t dev_addr,
+                          size_t size, int dir, struct dma_attrs *attrs)
 {
        char *dma_addr = bus_to_virt(dev_addr);
 
@@ -620,7 +617,14 @@ swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, size_t size,
        else if (dir == DMA_FROM_DEVICE)
                dma_mark_clean(dma_addr, size);
 }
+EXPORT_SYMBOL(swiotlb_unmap_single_attrs);
 
+void
+swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, size_t size,
+                    int dir)
+{
+       return swiotlb_unmap_single_attrs(hwdev, dev_addr, size, dir, NULL);
+}
 /*
  * Make physical memory consistent for a single streaming mode DMA translation
  * after a transfer.
@@ -691,6 +695,8 @@ swiotlb_sync_single_range_for_device(struct device *hwdev, dma_addr_t dev_addr,
                                  SYNC_FOR_DEVICE);
 }
 
+void swiotlb_unmap_sg_attrs(struct device *, struct scatterlist *, int, int,
+                           struct dma_attrs *);
 /*
  * Map a set of buffers described by scatterlist in streaming mode for DMA.
  * This is the scatter-gather version of the above swiotlb_map_single
@@ -708,8 +714,8 @@ swiotlb_sync_single_range_for_device(struct device *hwdev, dma_addr_t dev_addr,
  * same here.
  */
 int
-swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
-              int dir)
+swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
+                    int dir, struct dma_attrs *attrs)
 {
        struct scatterlist *sg;
        void *addr;
@@ -727,7 +733,8 @@ swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
                                /* Don't panic here, we expect map_sg users
                                   to do proper error handling. */
                                swiotlb_full(hwdev, sg->length, dir, 0);
-                               swiotlb_unmap_sg(hwdev, sgl, i, dir);
+                               swiotlb_unmap_sg_attrs(hwdev, sgl, i, dir,
+                                                      attrs);
                                sgl[0].dma_length = 0;
                                return 0;
                        }
@@ -738,14 +745,22 @@ swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
        }
        return nelems;
 }
+EXPORT_SYMBOL(swiotlb_map_sg_attrs);
+
+int
+swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
+              int dir)
+{
+       return swiotlb_map_sg_attrs(hwdev, sgl, nelems, dir, NULL);
+}
 
 /*
  * Unmap a set of streaming mode DMA translations.  Again, cpu read rules
  * concerning calls here are the same as for swiotlb_unmap_single() above.
  */
 void
-swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
-                int dir)
+swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
+                      int nelems, int dir, struct dma_attrs *attrs)
 {
        struct scatterlist *sg;
        int i;
@@ -760,6 +775,14 @@ swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
                        dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
        }
 }
+EXPORT_SYMBOL(swiotlb_unmap_sg_attrs);
+
+void
+swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
+                int dir)
+{
+       return swiotlb_unmap_sg_attrs(hwdev, sgl, nelems, dir, NULL);
+}
 
 /*
  * Make physical memory consistent for a set of streaming mode DMA translations
index e8644b1e5527df1069f968d17d1893fa0dc3e5fa..7c4f9e09709547eca3baeac0aaffa86ac9377e04 100644 (file)
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include <linux/module.h>
+#include <linux/writeback.h>
+#include <linux/device.h>
+
+
+static struct class *bdi_class;
+
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+static struct dentry *bdi_debug_root;
+
+static void bdi_debug_init(void)
+{
+       bdi_debug_root = debugfs_create_dir("bdi", NULL);
+}
+
+static int bdi_debug_stats_show(struct seq_file *m, void *v)
+{
+       struct backing_dev_info *bdi = m->private;
+       long background_thresh;
+       long dirty_thresh;
+       long bdi_thresh;
+
+       get_dirty_limits(&background_thresh, &dirty_thresh, &bdi_thresh, bdi);
+
+#define K(x) ((x) << (PAGE_SHIFT - 10))
+       seq_printf(m,
+                  "BdiWriteback:     %8lu kB\n"
+                  "BdiReclaimable:   %8lu kB\n"
+                  "BdiDirtyThresh:   %8lu kB\n"
+                  "DirtyThresh:      %8lu kB\n"
+                  "BackgroundThresh: %8lu kB\n",
+                  (unsigned long) K(bdi_stat(bdi, BDI_WRITEBACK)),
+                  (unsigned long) K(bdi_stat(bdi, BDI_RECLAIMABLE)),
+                  K(bdi_thresh),
+                  K(dirty_thresh),
+                  K(background_thresh));
+#undef K
+
+       return 0;
+}
+
+static int bdi_debug_stats_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, bdi_debug_stats_show, inode->i_private);
+}
+
+static const struct file_operations bdi_debug_stats_fops = {
+       .open           = bdi_debug_stats_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static void bdi_debug_register(struct backing_dev_info *bdi, const char *name)
+{
+       bdi->debug_dir = debugfs_create_dir(name, bdi_debug_root);
+       bdi->debug_stats = debugfs_create_file("stats", 0444, bdi->debug_dir,
+                                              bdi, &bdi_debug_stats_fops);
+}
+
+static void bdi_debug_unregister(struct backing_dev_info *bdi)
+{
+       debugfs_remove(bdi->debug_stats);
+       debugfs_remove(bdi->debug_dir);
+}
+#else
+static inline void bdi_debug_init(void)
+{
+}
+static inline void bdi_debug_register(struct backing_dev_info *bdi,
+                                     const char *name)
+{
+}
+static inline void bdi_debug_unregister(struct backing_dev_info *bdi)
+{
+}
+#endif
+
+static ssize_t read_ahead_kb_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t count)
+{
+       struct backing_dev_info *bdi = dev_get_drvdata(dev);
+       char *end;
+       unsigned long read_ahead_kb;
+       ssize_t ret = -EINVAL;
+
+       read_ahead_kb = simple_strtoul(buf, &end, 10);
+       if (*buf && (end[0] == '\0' || (end[0] == '\n' && end[1] == '\0'))) {
+               bdi->ra_pages = read_ahead_kb >> (PAGE_SHIFT - 10);
+               ret = count;
+       }
+       return ret;
+}
+
+#define K(pages) ((pages) << (PAGE_SHIFT - 10))
+
+#define BDI_SHOW(name, expr)                                           \
+static ssize_t name##_show(struct device *dev,                         \
+                          struct device_attribute *attr, char *page)   \
+{                                                                      \
+       struct backing_dev_info *bdi = dev_get_drvdata(dev);            \
+                                                                       \
+       return snprintf(page, PAGE_SIZE-1, "%lld\n", (long long)expr);  \
+}
+
+BDI_SHOW(read_ahead_kb, K(bdi->ra_pages))
+
+static ssize_t min_ratio_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct backing_dev_info *bdi = dev_get_drvdata(dev);
+       char *end;
+       unsigned int ratio;
+       ssize_t ret = -EINVAL;
+
+       ratio = simple_strtoul(buf, &end, 10);
+       if (*buf && (end[0] == '\0' || (end[0] == '\n' && end[1] == '\0'))) {
+               ret = bdi_set_min_ratio(bdi, ratio);
+               if (!ret)
+                       ret = count;
+       }
+       return ret;
+}
+BDI_SHOW(min_ratio, bdi->min_ratio)
+
+static ssize_t max_ratio_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct backing_dev_info *bdi = dev_get_drvdata(dev);
+       char *end;
+       unsigned int ratio;
+       ssize_t ret = -EINVAL;
+
+       ratio = simple_strtoul(buf, &end, 10);
+       if (*buf && (end[0] == '\0' || (end[0] == '\n' && end[1] == '\0'))) {
+               ret = bdi_set_max_ratio(bdi, ratio);
+               if (!ret)
+                       ret = count;
+       }
+       return ret;
+}
+BDI_SHOW(max_ratio, bdi->max_ratio)
+
+#define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store)
+
+static struct device_attribute bdi_dev_attrs[] = {
+       __ATTR_RW(read_ahead_kb),
+       __ATTR_RW(min_ratio),
+       __ATTR_RW(max_ratio),
+       __ATTR_NULL,
+};
+
+static __init int bdi_class_init(void)
+{
+       bdi_class = class_create(THIS_MODULE, "bdi");
+       bdi_class->dev_attrs = bdi_dev_attrs;
+       bdi_debug_init();
+       return 0;
+}
+
+postcore_initcall(bdi_class_init);
+
+int bdi_register(struct backing_dev_info *bdi, struct device *parent,
+               const char *fmt, ...)
+{
+       char *name;
+       va_list args;
+       int ret = 0;
+       struct device *dev;
+
+       va_start(args, fmt);
+       name = kvasprintf(GFP_KERNEL, fmt, args);
+       va_end(args);
+
+       if (!name)
+               return -ENOMEM;
+
+       dev = device_create(bdi_class, parent, MKDEV(0, 0), name);
+       if (IS_ERR(dev)) {
+               ret = PTR_ERR(dev);
+               goto exit;
+       }
+
+       bdi->dev = dev;
+       dev_set_drvdata(bdi->dev, bdi);
+       bdi_debug_register(bdi, name);
+
+exit:
+       kfree(name);
+       return ret;
+}
+EXPORT_SYMBOL(bdi_register);
+
+int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev)
+{
+       return bdi_register(bdi, NULL, "%u:%u", MAJOR(dev), MINOR(dev));
+}
+EXPORT_SYMBOL(bdi_register_dev);
+
+void bdi_unregister(struct backing_dev_info *bdi)
+{
+       if (bdi->dev) {
+               bdi_debug_unregister(bdi);
+               device_unregister(bdi->dev);
+               bdi->dev = NULL;
+       }
+}
+EXPORT_SYMBOL(bdi_unregister);
 
 int bdi_init(struct backing_dev_info *bdi)
 {
        int i;
        int err;
 
+       bdi->dev = NULL;
+
+       bdi->min_ratio = 0;
+       bdi->max_ratio = 100;
+       bdi->max_prop_frac = PROP_FRAC_BASE;
+
        for (i = 0; i < NR_BDI_STAT_ITEMS; i++) {
                err = percpu_counter_init_irq(&bdi->bdi_stat[i], 0);
                if (err)
@@ -33,6 +250,8 @@ void bdi_destroy(struct backing_dev_info *bdi)
 {
        int i;
 
+       bdi_unregister(bdi);
+
        for (i = 0; i < NR_BDI_STAT_ITEMS; i++)
                percpu_counter_destroy(&bdi->bdi_stat[i]);
 
index 2c37c67ed8c90f0cb64265519ad794abcb275a1d..bbf953eeb58bafbad0016a6f73db4844e5514c22 100644 (file)
@@ -199,7 +199,8 @@ static struct page *alloc_fresh_huge_page_node(int nid)
        struct page *page;
 
        page = alloc_pages_node(nid,
-               htlb_alloc_mask|__GFP_COMP|__GFP_THISNODE|__GFP_NOWARN,
+               htlb_alloc_mask|__GFP_COMP|__GFP_THISNODE|
+                                               __GFP_REPEAT|__GFP_NOWARN,
                HUGETLB_PAGE_ORDER);
        if (page) {
                if (arch_prepare_hugepage(page)) {
@@ -294,7 +295,8 @@ static struct page *alloc_buddy_huge_page(struct vm_area_struct *vma,
        }
        spin_unlock(&hugetlb_lock);
 
-       page = alloc_pages(htlb_alloc_mask|__GFP_COMP|__GFP_NOWARN,
+       page = alloc_pages(htlb_alloc_mask|__GFP_COMP|
+                                       __GFP_REPEAT|__GFP_NOWARN,
                                        HUGETLB_PAGE_ORDER);
 
        spin_lock(&hugetlb_lock);
index 2e0bfc93484b327557e6b88f509476c4f837ac8f..33add96cd5fbf98c2f804fb2511aeec3f5a2594d 100644 (file)
 #include <linux/backing-dev.h>
 #include <linux/bit_spinlock.h>
 #include <linux/rcupdate.h>
+#include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/spinlock.h>
 #include <linux/fs.h>
 #include <linux/seq_file.h>
+#include <linux/vmalloc.h>
 
 #include <asm/uaccess.h>
 
 struct cgroup_subsys mem_cgroup_subsys;
 static const int MEM_CGROUP_RECLAIM_RETRIES = 5;
+static struct kmem_cache *page_cgroup_cache;
 
 /*
  * Statistics for memory cgroup.
@@ -236,26 +239,12 @@ static struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont)
                                css);
 }
 
-static struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p)
+struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p)
 {
        return container_of(task_subsys_state(p, mem_cgroup_subsys_id),
                                struct mem_cgroup, css);
 }
 
-void mm_init_cgroup(struct mm_struct *mm, struct task_struct *p)
-{
-       struct mem_cgroup *mem;
-
-       mem = mem_cgroup_from_task(p);
-       css_get(&mem->css);
-       mm->mem_cgroup = mem;
-}
-
-void mm_free_cgroup(struct mm_struct *mm)
-{
-       css_put(&mm->mem_cgroup->css);
-}
-
 static inline int page_cgroup_locked(struct page *page)
 {
        return bit_spin_is_locked(PAGE_CGROUP_LOCK_BIT, &page->page_cgroup);
@@ -287,10 +276,10 @@ static void unlock_page_cgroup(struct page *page)
        bit_spin_unlock(PAGE_CGROUP_LOCK_BIT, &page->page_cgroup);
 }
 
-static void __mem_cgroup_remove_list(struct page_cgroup *pc)
+static void __mem_cgroup_remove_list(struct mem_cgroup_per_zone *mz,
+                       struct page_cgroup *pc)
 {
        int from = pc->flags & PAGE_CGROUP_FLAG_ACTIVE;
-       struct mem_cgroup_per_zone *mz = page_cgroup_zoneinfo(pc);
 
        if (from)
                MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_ACTIVE) -= 1;
@@ -301,10 +290,10 @@ static void __mem_cgroup_remove_list(struct page_cgroup *pc)
        list_del_init(&pc->lru);
 }
 
-static void __mem_cgroup_add_list(struct page_cgroup *pc)
+static void __mem_cgroup_add_list(struct mem_cgroup_per_zone *mz,
+                               struct page_cgroup *pc)
 {
        int to = pc->flags & PAGE_CGROUP_FLAG_ACTIVE;
-       struct mem_cgroup_per_zone *mz = page_cgroup_zoneinfo(pc);
 
        if (!to) {
                MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_INACTIVE) += 1;
@@ -476,6 +465,7 @@ unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
        int zid = zone_idx(z);
        struct mem_cgroup_per_zone *mz;
 
+       BUG_ON(!mem_cont);
        mz = mem_cgroup_zoneinfo(mem_cont, nid, zid);
        if (active)
                src = &mz->active_list;
@@ -560,7 +550,7 @@ retry:
        }
        unlock_page_cgroup(page);
 
-       pc = kzalloc(sizeof(struct page_cgroup), gfp_mask);
+       pc = kmem_cache_zalloc(page_cgroup_cache, gfp_mask);
        if (pc == NULL)
                goto err;
 
@@ -574,7 +564,7 @@ retry:
                mm = &init_mm;
 
        rcu_read_lock();
-       mem = rcu_dereference(mm->mem_cgroup);
+       mem = mem_cgroup_from_task(rcu_dereference(mm->owner));
        /*
         * For every charge from the cgroup, increment reference count
         */
@@ -602,7 +592,6 @@ retry:
                        mem_cgroup_out_of_memory(mem, gfp_mask);
                        goto out;
                }
-               congestion_wait(WRITE, HZ/10);
        }
 
        pc->ref_cnt = 1;
@@ -610,7 +599,7 @@ retry:
        pc->page = page;
        pc->flags = PAGE_CGROUP_FLAG_ACTIVE;
        if (ctype == MEM_CGROUP_CHARGE_TYPE_CACHE)
-               pc->flags |= PAGE_CGROUP_FLAG_CACHE;
+               pc->flags = PAGE_CGROUP_FLAG_CACHE;
 
        lock_page_cgroup(page);
        if (page_get_page_cgroup(page)) {
@@ -622,14 +611,14 @@ retry:
                 */
                res_counter_uncharge(&mem->res, PAGE_SIZE);
                css_put(&mem->css);
-               kfree(pc);
+               kmem_cache_free(page_cgroup_cache, pc);
                goto retry;
        }
        page_assign_page_cgroup(page, pc);
 
        mz = page_cgroup_zoneinfo(pc);
        spin_lock_irqsave(&mz->lru_lock, flags);
-       __mem_cgroup_add_list(pc);
+       __mem_cgroup_add_list(mz, pc);
        spin_unlock_irqrestore(&mz->lru_lock, flags);
 
        unlock_page_cgroup(page);
@@ -637,7 +626,7 @@ done:
        return 0;
 out:
        css_put(&mem->css);
-       kfree(pc);
+       kmem_cache_free(page_cgroup_cache, pc);
 err:
        return -ENOMEM;
 }
@@ -685,7 +674,7 @@ void mem_cgroup_uncharge_page(struct page *page)
        if (--(pc->ref_cnt) == 0) {
                mz = page_cgroup_zoneinfo(pc);
                spin_lock_irqsave(&mz->lru_lock, flags);
-               __mem_cgroup_remove_list(pc);
+               __mem_cgroup_remove_list(mz, pc);
                spin_unlock_irqrestore(&mz->lru_lock, flags);
 
                page_assign_page_cgroup(page, NULL);
@@ -695,7 +684,7 @@ void mem_cgroup_uncharge_page(struct page *page)
                res_counter_uncharge(&mem->res, PAGE_SIZE);
                css_put(&mem->css);
 
-               kfree(pc);
+               kmem_cache_free(page_cgroup_cache, pc);
                return;
        }
 
@@ -747,7 +736,7 @@ void mem_cgroup_page_migration(struct page *page, struct page *newpage)
 
        mz = page_cgroup_zoneinfo(pc);
        spin_lock_irqsave(&mz->lru_lock, flags);
-       __mem_cgroup_remove_list(pc);
+       __mem_cgroup_remove_list(mz, pc);
        spin_unlock_irqrestore(&mz->lru_lock, flags);
 
        page_assign_page_cgroup(page, NULL);
@@ -759,7 +748,7 @@ void mem_cgroup_page_migration(struct page *page, struct page *newpage)
 
        mz = page_cgroup_zoneinfo(pc);
        spin_lock_irqsave(&mz->lru_lock, flags);
-       __mem_cgroup_add_list(pc);
+       __mem_cgroup_add_list(mz, pc);
        spin_unlock_irqrestore(&mz->lru_lock, flags);
 
        unlock_page_cgroup(newpage);
@@ -853,13 +842,10 @@ static int mem_cgroup_write_strategy(char *buf, unsigned long long *tmp)
        return 0;
 }
 
-static ssize_t mem_cgroup_read(struct cgroup *cont,
-                       struct cftype *cft, struct file *file,
-                       char __user *userbuf, size_t nbytes, loff_t *ppos)
+static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft)
 {
-       return res_counter_read(&mem_cgroup_from_cont(cont)->res,
-                               cft->private, userbuf, nbytes, ppos,
-                               NULL);
+       return res_counter_read_u64(&mem_cgroup_from_cont(cont)->res,
+                                   cft->private);
 }
 
 static ssize_t mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
@@ -871,27 +857,25 @@ static ssize_t mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
                                mem_cgroup_write_strategy);
 }
 
-static ssize_t mem_force_empty_write(struct cgroup *cont,
-                               struct cftype *cft, struct file *file,
-                               const char __user *userbuf,
-                               size_t nbytes, loff_t *ppos)
+static int mem_cgroup_reset(struct cgroup *cont, unsigned int event)
 {
-       struct mem_cgroup *mem = mem_cgroup_from_cont(cont);
-       int ret = mem_cgroup_force_empty(mem);
-       if (!ret)
-               ret = nbytes;
-       return ret;
+       struct mem_cgroup *mem;
+
+       mem = mem_cgroup_from_cont(cont);
+       switch (event) {
+       case RES_MAX_USAGE:
+               res_counter_reset_max(&mem->res);
+               break;
+       case RES_FAILCNT:
+               res_counter_reset_failcnt(&mem->res);
+               break;
+       }
+       return 0;
 }
 
-/*
- * Note: This should be removed if cgroup supports write-only file.
- */
-static ssize_t mem_force_empty_read(struct cgroup *cont,
-                               struct cftype *cft,
-                               struct file *file, char __user *userbuf,
-                               size_t nbytes, loff_t *ppos)
+static int mem_force_empty_write(struct cgroup *cont, unsigned int event)
 {
-       return -EINVAL;
+       return mem_cgroup_force_empty(mem_cgroup_from_cont(cont));
 }
 
 static const struct mem_cgroup_stat_desc {
@@ -902,9 +886,9 @@ static const struct mem_cgroup_stat_desc {
        [MEM_CGROUP_STAT_RSS] = { "rss", PAGE_SIZE, },
 };
 
-static int mem_control_stat_show(struct seq_file *m, void *arg)
+static int mem_control_stat_show(struct cgroup *cont, struct cftype *cft,
+                                struct cgroup_map_cb *cb)
 {
-       struct cgroup *cont = m->private;
        struct mem_cgroup *mem_cont = mem_cgroup_from_cont(cont);
        struct mem_cgroup_stat *stat = &mem_cont->stat;
        int i;
@@ -914,8 +898,7 @@ static int mem_control_stat_show(struct seq_file *m, void *arg)
 
                val = mem_cgroup_read_stat(stat, i);
                val *= mem_cgroup_stat_desc[i].unit;
-               seq_printf(m, "%s %lld\n", mem_cgroup_stat_desc[i].msg,
-                               (long long)val);
+               cb->fill(cb, mem_cgroup_stat_desc[i].msg, val);
        }
        /* showing # of active pages */
        {
@@ -925,52 +908,43 @@ static int mem_control_stat_show(struct seq_file *m, void *arg)
                                                MEM_CGROUP_ZSTAT_INACTIVE);
                active = mem_cgroup_get_all_zonestat(mem_cont,
                                                MEM_CGROUP_ZSTAT_ACTIVE);
-               seq_printf(m, "active %ld\n", (active) * PAGE_SIZE);
-               seq_printf(m, "inactive %ld\n", (inactive) * PAGE_SIZE);
+               cb->fill(cb, "active", (active) * PAGE_SIZE);
+               cb->fill(cb, "inactive", (inactive) * PAGE_SIZE);
        }
        return 0;
 }
 
-static const struct file_operations mem_control_stat_file_operations = {
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-static int mem_control_stat_open(struct inode *unused, struct file *file)
-{
-       /* XXX __d_cont */
-       struct cgroup *cont = file->f_dentry->d_parent->d_fsdata;
-
-       file->f_op = &mem_control_stat_file_operations;
-       return single_open(file, mem_control_stat_show, cont);
-}
-
 static struct cftype mem_cgroup_files[] = {
        {
                .name = "usage_in_bytes",
                .private = RES_USAGE,
-               .read = mem_cgroup_read,
+               .read_u64 = mem_cgroup_read,
+       },
+       {
+               .name = "max_usage_in_bytes",
+               .private = RES_MAX_USAGE,
+               .trigger = mem_cgroup_reset,
+               .read_u64 = mem_cgroup_read,
        },
        {
                .name = "limit_in_bytes",
                .private = RES_LIMIT,
                .write = mem_cgroup_write,
-               .read = mem_cgroup_read,
+               .read_u64 = mem_cgroup_read,
        },
        {
                .name = "failcnt",
                .private = RES_FAILCNT,
-               .read = mem_cgroup_read,
+               .trigger = mem_cgroup_reset,
+               .read_u64 = mem_cgroup_read,
        },
        {
                .name = "force_empty",
-               .write = mem_force_empty_write,
-               .read = mem_force_empty_read,
+               .trigger = mem_force_empty_write,
        },
        {
                .name = "stat",
-               .open = mem_control_stat_open,
+               .read_map = mem_control_stat_show,
        },
 };
 
@@ -1010,6 +984,29 @@ static void free_mem_cgroup_per_zone_info(struct mem_cgroup *mem, int node)
        kfree(mem->info.nodeinfo[node]);
 }
 
+static struct mem_cgroup *mem_cgroup_alloc(void)
+{
+       struct mem_cgroup *mem;
+
+       if (sizeof(*mem) < PAGE_SIZE)
+               mem = kmalloc(sizeof(*mem), GFP_KERNEL);
+       else
+               mem = vmalloc(sizeof(*mem));
+
+       if (mem)
+               memset(mem, 0, sizeof(*mem));
+       return mem;
+}
+
+static void mem_cgroup_free(struct mem_cgroup *mem)
+{
+       if (sizeof(*mem) < PAGE_SIZE)
+               kfree(mem);
+       else
+               vfree(mem);
+}
+
+
 static struct cgroup_subsys_state *
 mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
 {
@@ -1018,17 +1015,15 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
 
        if (unlikely((cont->parent) == NULL)) {
                mem = &init_mem_cgroup;
-               init_mm.mem_cgroup = mem;
-       } else
-               mem = kzalloc(sizeof(struct mem_cgroup), GFP_KERNEL);
-
-       if (mem == NULL)
-               return ERR_PTR(-ENOMEM);
+               page_cgroup_cache = KMEM_CACHE(page_cgroup, SLAB_PANIC);
+       } else {
+               mem = mem_cgroup_alloc();
+               if (!mem)
+                       return ERR_PTR(-ENOMEM);
+       }
 
        res_counter_init(&mem->res);
 
-       memset(&mem->info, 0, sizeof(mem->info));
-
        for_each_node_state(node, N_POSSIBLE)
                if (alloc_mem_cgroup_per_zone_info(mem, node))
                        goto free_out;
@@ -1038,7 +1033,7 @@ free_out:
        for_each_node_state(node, N_POSSIBLE)
                free_mem_cgroup_per_zone_info(mem, node);
        if (cont->parent != NULL)
-               kfree(mem);
+               mem_cgroup_free(mem);
        return ERR_PTR(-ENOMEM);
 }
 
@@ -1058,7 +1053,7 @@ static void mem_cgroup_destroy(struct cgroup_subsys *ss,
        for_each_node_state(node, N_POSSIBLE)
                free_mem_cgroup_per_zone_info(mem, node);
 
-       kfree(mem_cgroup_from_cont(cont));
+       mem_cgroup_free(mem_cgroup_from_cont(cont));
 }
 
 static int mem_cgroup_populate(struct cgroup_subsys *ss,
@@ -1098,10 +1093,6 @@ static void mem_cgroup_move_task(struct cgroup_subsys *ss,
        if (!thread_group_leader(p))
                goto out;
 
-       css_get(&mem->css);
-       rcu_assign_pointer(mm->mem_cgroup, mem);
-       css_put(&old_mem->css);
-
 out:
        mmput(mm);
 }
index 4e0eccca5e265ac19bc507a171a2f720d27f8c21..449d77d409f52622bbf825b7fd17d43df7ff5fbf 100644 (file)
@@ -383,7 +383,14 @@ static void migrate_page_copy(struct page *newpage, struct page *page)
 
        if (PageDirty(page)) {
                clear_page_dirty_for_io(page);
-               set_page_dirty(newpage);
+               /*
+                * Want to mark the page and the radix tree as dirty, and
+                * redo the accounting that clear_page_dirty_for_io undid,
+                * but we can't use set_page_dirty because that function
+                * is actually a signal that all of the page has become dirty.
+                * Wheras only part of our page may be dirty.
+                */
+               __set_page_dirty_nobuffers(newpage);
        }
 
 #ifdef CONFIG_SWAP
index 677d184b0d42d0d9d10311569872589b7a1e2ef4..fac66337da2a3bcd3a003ba9d33096938c17fb57 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -230,8 +230,11 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma)
        might_sleep();
        if (vma->vm_ops && vma->vm_ops->close)
                vma->vm_ops->close(vma);
-       if (vma->vm_file)
+       if (vma->vm_file) {
                fput(vma->vm_file);
+               if (vma->vm_flags & VM_EXECUTABLE)
+                       removed_exe_file_vma(vma->vm_mm);
+       }
        mpol_put(vma_policy(vma));
        kmem_cache_free(vm_area_cachep, vma);
        return next;
@@ -623,8 +626,11 @@ again:                     remove_next = 1 + (end > next->vm_end);
                spin_unlock(&mapping->i_mmap_lock);
 
        if (remove_next) {
-               if (file)
+               if (file) {
                        fput(file);
+                       if (next->vm_flags & VM_EXECUTABLE)
+                               removed_exe_file_vma(mm);
+               }
                mm->map_count--;
                mpol_put(vma_policy(next));
                kmem_cache_free(vm_area_cachep, next);
@@ -1154,6 +1160,8 @@ munmap_back:
                error = file->f_op->mmap(file, vma);
                if (error)
                        goto unmap_and_free_vma;
+               if (vm_flags & VM_EXECUTABLE)
+                       added_exe_file_vma(mm);
        } else if (vm_flags & VM_SHARED) {
                error = shmem_zero_setup(vma);
                if (error)
@@ -1185,6 +1193,8 @@ munmap_back:
                mpol_put(vma_policy(vma));
                kmem_cache_free(vm_area_cachep, vma);
                fput(file);
+               if (vm_flags & VM_EXECUTABLE)
+                       removed_exe_file_vma(mm);
        } else {
                vma_link(mm, vma, prev, rb_link, rb_parent);
                file = vma->vm_file;
@@ -1817,8 +1827,11 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
        }
        vma_set_policy(new, pol);
 
-       if (new->vm_file)
+       if (new->vm_file) {
                get_file(new->vm_file);
+               if (vma->vm_flags & VM_EXECUTABLE)
+                       added_exe_file_vma(mm);
+       }
 
        if (new->vm_ops && new->vm_ops->open)
                new->vm_ops->open(new);
@@ -2135,8 +2148,11 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
                        new_vma->vm_start = addr;
                        new_vma->vm_end = addr + len;
                        new_vma->vm_pgoff = pgoff;
-                       if (new_vma->vm_file)
+                       if (new_vma->vm_file) {
                                get_file(new_vma->vm_file);
+                               if (vma->vm_flags & VM_EXECUTABLE)
+                                       added_exe_file_vma(mm);
+                       }
                        if (new_vma->vm_ops && new_vma->vm_ops->open)
                                new_vma->vm_ops->open(new_vma);
                        vma_link(mm, new_vma, prev, rb_link, rb_parent);
index 1d32fe89d57b18642283a419600828584354d469..ef8c62cec697a06495b13f2658aff4e30000065c 100644 (file)
@@ -966,8 +966,13 @@ unsigned long do_mmap_pgoff(struct file *file,
 
        INIT_LIST_HEAD(&vma->anon_vma_node);
        atomic_set(&vma->vm_usage, 1);
-       if (file)
+       if (file) {
                get_file(file);
+               if (vm_flags & VM_EXECUTABLE) {
+                       added_exe_file_vma(current->mm);
+                       vma->vm_mm = current->mm;
+               }
+       }
        vma->vm_file    = file;
        vma->vm_flags   = vm_flags;
        vma->vm_start   = addr;
@@ -1022,8 +1027,11 @@ unsigned long do_mmap_pgoff(struct file *file,
        up_write(&nommu_vma_sem);
        kfree(vml);
        if (vma) {
-               if (vma->vm_file)
+               if (vma->vm_file) {
                        fput(vma->vm_file);
+                       if (vma->vm_flags & VM_EXECUTABLE)
+                               removed_exe_file_vma(vma->vm_mm);
+               }
                kfree(vma);
        }
        return ret;
@@ -1053,7 +1061,7 @@ EXPORT_SYMBOL(do_mmap_pgoff);
 /*
  * handle mapping disposal for uClinux
  */
-static void put_vma(struct vm_area_struct *vma)
+static void put_vma(struct mm_struct *mm, struct vm_area_struct *vma)
 {
        if (vma) {
                down_write(&nommu_vma_sem);
@@ -1075,8 +1083,11 @@ static void put_vma(struct vm_area_struct *vma)
                        realalloc -= kobjsize(vma);
                        askedalloc -= sizeof(*vma);
 
-                       if (vma->vm_file)
+                       if (vma->vm_file) {
                                fput(vma->vm_file);
+                               if (vma->vm_flags & VM_EXECUTABLE)
+                                       removed_exe_file_vma(mm);
+                       }
                        kfree(vma);
                }
 
@@ -1113,7 +1124,7 @@ int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
  found:
        vml = *parent;
 
-       put_vma(vml->vma);
+       put_vma(mm, vml->vma);
 
        *parent = vml->next;
        realalloc -= kobjsize(vml);
@@ -1158,7 +1169,7 @@ void exit_mmap(struct mm_struct * mm)
 
                while ((tmp = mm->context.vmlist)) {
                        mm->context.vmlist = tmp->next;
-                       put_vma(tmp->vma);
+                       put_vma(mm, tmp->vma);
 
                        realalloc -= kobjsize(tmp);
                        askedalloc -= sizeof(*tmp);
index 5e00f1772c20fc6d9e4e70a087800e93b3ae3df2..789b6adbef37f1f38c3887f10ba130595903408a 100644 (file)
@@ -164,9 +164,20 @@ int dirty_ratio_handler(struct ctl_table *table, int write,
  */
 static inline void __bdi_writeout_inc(struct backing_dev_info *bdi)
 {
-       __prop_inc_percpu(&vm_completions, &bdi->completions);
+       __prop_inc_percpu_max(&vm_completions, &bdi->completions,
+                             bdi->max_prop_frac);
 }
 
+void bdi_writeout_inc(struct backing_dev_info *bdi)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       __bdi_writeout_inc(bdi);
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(bdi_writeout_inc);
+
 static inline void task_dirty_inc(struct task_struct *tsk)
 {
        prop_inc_single(&vm_dirties, &tsk->dirties);
@@ -200,7 +211,8 @@ clip_bdi_dirty_limit(struct backing_dev_info *bdi, long dirty, long *pbdi_dirty)
        avail_dirty = dirty -
                (global_page_state(NR_FILE_DIRTY) +
                 global_page_state(NR_WRITEBACK) +
-                global_page_state(NR_UNSTABLE_NFS));
+                global_page_state(NR_UNSTABLE_NFS) +
+                global_page_state(NR_WRITEBACK_TEMP));
 
        if (avail_dirty < 0)
                avail_dirty = 0;
@@ -242,6 +254,55 @@ static void task_dirty_limit(struct task_struct *tsk, long *pdirty)
        *pdirty = dirty;
 }
 
+/*
+ *
+ */
+static DEFINE_SPINLOCK(bdi_lock);
+static unsigned int bdi_min_ratio;
+
+int bdi_set_min_ratio(struct backing_dev_info *bdi, unsigned int min_ratio)
+{
+       int ret = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&bdi_lock, flags);
+       if (min_ratio > bdi->max_ratio) {
+               ret = -EINVAL;
+       } else {
+               min_ratio -= bdi->min_ratio;
+               if (bdi_min_ratio + min_ratio < 100) {
+                       bdi_min_ratio += min_ratio;
+                       bdi->min_ratio += min_ratio;
+               } else {
+                       ret = -EINVAL;
+               }
+       }
+       spin_unlock_irqrestore(&bdi_lock, flags);
+
+       return ret;
+}
+
+int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned max_ratio)
+{
+       unsigned long flags;
+       int ret = 0;
+
+       if (max_ratio > 100)
+               return -EINVAL;
+
+       spin_lock_irqsave(&bdi_lock, flags);
+       if (bdi->min_ratio > max_ratio) {
+               ret = -EINVAL;
+       } else {
+               bdi->max_ratio = max_ratio;
+               bdi->max_prop_frac = (PROP_FRAC_BASE * max_ratio) / 100;
+       }
+       spin_unlock_irqrestore(&bdi_lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL(bdi_set_max_ratio);
+
 /*
  * Work out the current dirty-memory clamping and background writeout
  * thresholds.
@@ -300,7 +361,7 @@ static unsigned long determine_dirtyable_memory(void)
        return x + 1;   /* Ensure that we never return 0 */
 }
 
-static void
+void
 get_dirty_limits(long *pbackground, long *pdirty, long *pbdi_dirty,
                 struct backing_dev_info *bdi)
 {
@@ -330,7 +391,7 @@ get_dirty_limits(long *pbackground, long *pdirty, long *pbdi_dirty,
        *pdirty = dirty;
 
        if (bdi) {
-               u64 bdi_dirty = dirty;
+               u64 bdi_dirty;
                long numerator, denominator;
 
                /*
@@ -338,8 +399,12 @@ get_dirty_limits(long *pbackground, long *pdirty, long *pbdi_dirty,
                 */
                bdi_writeout_fraction(bdi, &numerator, &denominator);
 
+               bdi_dirty = (dirty * (100 - bdi_min_ratio)) / 100;
                bdi_dirty *= numerator;
                do_div(bdi_dirty, denominator);
+               bdi_dirty += (dirty * bdi->min_ratio) / 100;
+               if (bdi_dirty > (dirty * bdi->max_ratio) / 100)
+                       bdi_dirty = dirty * bdi->max_ratio / 100;
 
                *pbdi_dirty = bdi_dirty;
                clip_bdi_dirty_limit(bdi, dirty, pbdi_dirty);
@@ -1192,7 +1257,7 @@ int test_clear_page_writeback(struct page *page)
                        radix_tree_tag_clear(&mapping->page_tree,
                                                page_index(page),
                                                PAGECACHE_TAG_WRITEBACK);
-                       if (bdi_cap_writeback_dirty(bdi)) {
+                       if (bdi_cap_account_writeback(bdi)) {
                                __dec_bdi_stat(bdi, BDI_WRITEBACK);
                                __bdi_writeout_inc(bdi);
                        }
@@ -1221,7 +1286,7 @@ int test_set_page_writeback(struct page *page)
                        radix_tree_tag_set(&mapping->page_tree,
                                                page_index(page),
                                                PAGECACHE_TAG_WRITEBACK);
-                       if (bdi_cap_writeback_dirty(bdi))
+                       if (bdi_cap_account_writeback(bdi))
                                __inc_bdi_stat(bdi, BDI_WRITEBACK);
                }
                if (!PageDirty(page))
index d1cf4f05dcdaff12c4e261495efe53a3b3dd7209..bdd5c432c426fdf6714ff90e1eebdfccfdccee8c 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/fault-inject.h>
 #include <linux/page-isolation.h>
 #include <linux/memcontrol.h>
+#include <linux/debugobjects.h>
 
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
@@ -532,8 +533,11 @@ static void __free_pages_ok(struct page *page, unsigned int order)
        if (reserved)
                return;
 
-       if (!PageHighMem(page))
+       if (!PageHighMem(page)) {
                debug_check_no_locks_freed(page_address(page),PAGE_SIZE<<order);
+               debug_check_no_obj_freed(page_address(page),
+                                          PAGE_SIZE << order);
+       }
        arch_free_page(page, order);
        kernel_map_pages(page, 1 << order, 0);
 
@@ -995,8 +999,10 @@ static void free_hot_cold_page(struct page *page, int cold)
        if (free_pages_check(page))
                return;
 
-       if (!PageHighMem(page))
+       if (!PageHighMem(page)) {
                debug_check_no_locks_freed(page_address(page), PAGE_SIZE);
+               debug_check_no_obj_freed(page_address(page), PAGE_SIZE);
+       }
        arch_free_page(page, 0);
        kernel_map_pages(page, 1, 0);
 
@@ -1461,7 +1467,8 @@ __alloc_pages_internal(gfp_t gfp_mask, unsigned int order,
        struct task_struct *p = current;
        int do_retry;
        int alloc_flags;
-       int did_some_progress;
+       unsigned long did_some_progress;
+       unsigned long pages_reclaimed = 0;
 
        might_sleep_if(wait);
 
@@ -1611,14 +1618,26 @@ nofail_alloc:
         * Don't let big-order allocations loop unless the caller explicitly
         * requests that.  Wait for some write requests to complete then retry.
         *
-        * In this implementation, __GFP_REPEAT means __GFP_NOFAIL for order
-        * <= 3, but that may not be true in other implementations.
+        * In this implementation, order <= PAGE_ALLOC_COSTLY_ORDER
+        * means __GFP_NOFAIL, but that may not be true in other
+        * implementations.
+        *
+        * For order > PAGE_ALLOC_COSTLY_ORDER, if __GFP_REPEAT is
+        * specified, then we retry until we no longer reclaim any pages
+        * (above), or we've reclaimed an order of pages at least as
+        * large as the allocation's order. In both cases, if the
+        * allocation still fails, we stop retrying.
         */
+       pages_reclaimed += did_some_progress;
        do_retry = 0;
        if (!(gfp_mask & __GFP_NORETRY)) {
-               if ((order <= PAGE_ALLOC_COSTLY_ORDER) ||
-                                               (gfp_mask & __GFP_REPEAT))
+               if (order <= PAGE_ALLOC_COSTLY_ORDER) {
                        do_retry = 1;
+               } else {
+                       if (gfp_mask & __GFP_REPEAT &&
+                               pages_reclaimed < (1 << order))
+                                       do_retry = 1;
+               }
                if (gfp_mask & __GFP_NOFAIL)
                        do_retry = 1;
        }
@@ -2524,7 +2543,9 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
        struct page *page;
        unsigned long end_pfn = start_pfn + size;
        unsigned long pfn;
+       struct zone *z;
 
+       z = &NODE_DATA(nid)->node_zones[zone];
        for (pfn = start_pfn; pfn < end_pfn; pfn++) {
                /*
                 * There can be holes in boot-time mem_map[]s
@@ -2542,7 +2563,6 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
                init_page_count(page);
                reset_page_mapcount(page);
                SetPageReserved(page);
-
                /*
                 * Mark the block movable so that blocks are reserved for
                 * movable at startup. This will force kernel allocations
@@ -2551,8 +2571,15 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
                 * kernel allocations are made. Later some blocks near
                 * the start are marked MIGRATE_RESERVE by
                 * setup_zone_migrate_reserve()
+                *
+                * bitmap is created for zone's valid pfn range. but memmap
+                * can be created for invalid pages (for alignment)
+                * check here not to call set_pageblock_migratetype() against
+                * pfn out of zone.
                 */
-               if ((pfn & (pageblock_nr_pages-1)))
+               if ((z->zone_start_pfn <= pfn)
+                   && (pfn < z->zone_start_pfn + z->spanned_pages)
+                   && !(pfn & (pageblock_nr_pages - 1)))
                        set_pageblock_migratetype(page, MIGRATE_MOVABLE);
 
                INIT_LIST_HEAD(&page->lru);
@@ -4464,6 +4491,8 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags,
        pfn = page_to_pfn(page);
        bitmap = get_pageblock_bitmap(zone, pfn);
        bitidx = pfn_to_bitidx(zone, pfn);
+       VM_BUG_ON(pfn < zone->zone_start_pfn);
+       VM_BUG_ON(pfn >= zone->zone_start_pfn + zone->spanned_pages);
 
        for (; start_bitidx <= end_bitidx; start_bitidx++, value <<= 1)
                if (flags & value)
index 8762e8988972baa01820369ba1fd46d7e727d215..d8723a5f6496d05af23445e6ae862754e9d41214 100644 (file)
@@ -235,7 +235,13 @@ unsigned long max_sane_readahead(unsigned long nr)
 
 static int __init readahead_init(void)
 {
-       return bdi_init(&default_backing_dev_info);
+       int err;
+
+       err = bdi_init(&default_backing_dev_info);
+       if (!err)
+               bdi_register(&default_backing_dev_info, NULL, "default");
+
+       return err;
 }
 subsys_initcall(readahead_init);
 
index e6d9298aa22a1e814734c940154e9afa519a8f46..e2a6ae1a44e9a5e8b5e6594d11f76b11a02ea49f 100644 (file)
@@ -201,7 +201,7 @@ static struct vm_operations_struct shmem_vm_ops;
 
 static struct backing_dev_info shmem_backing_dev_info  __read_mostly = {
        .ra_pages       = 0,    /* No readahead */
-       .capabilities   = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
+       .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK,
        .unplug_io_fn   = default_unplug_io_fn,
 };
 
index 39d20f8a07916fc7bf77a8153d58c0cf8161c90e..06236e4ddc1b99686d64683865ca648ed2f79864 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
 #include       <linux/fault-inject.h>
 #include       <linux/rtmutex.h>
 #include       <linux/reciprocal_div.h>
+#include       <linux/debugobjects.h>
 
 #include       <asm/cacheflush.h>
 #include       <asm/tlbflush.h>
                         SLAB_CACHE_DMA | \
                         SLAB_STORE_USER | \
                         SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \
-                        SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD)
+                        SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD | \
+                        SLAB_DEBUG_OBJECTS)
 #else
 # define CREATE_MASK   (SLAB_HWCACHE_ALIGN | \
                         SLAB_CACHE_DMA | \
                         SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \
-                        SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD)
+                        SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD | \
+                        SLAB_DEBUG_OBJECTS)
 #endif
 
 /*
@@ -858,7 +861,7 @@ static void cache_estimate(unsigned long gfporder, size_t buffer_size,
        *left_over = slab_size - nr_objs*buffer_size - mgmt_size;
 }
 
-#define slab_error(cachep, msg) __slab_error(__FUNCTION__, cachep, msg)
+#define slab_error(cachep, msg) __slab_error(__func__, cachep, msg)
 
 static void __slab_error(const char *function, struct kmem_cache *cachep,
                        char *msg)
@@ -2153,7 +2156,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
         */
        if (!name || in_interrupt() || (size < BYTES_PER_WORD) ||
            size > KMALLOC_MAX_SIZE) {
-               printk(KERN_ERR "%s: Early error in slab %s\n", __FUNCTION__,
+               printk(KERN_ERR "%s: Early error in slab %s\n", __func__,
                                name);
                BUG();
        }
@@ -3760,6 +3763,8 @@ void kmem_cache_free(struct kmem_cache *cachep, void *objp)
 
        local_irq_save(flags);
        debug_check_no_locks_freed(objp, obj_size(cachep));
+       if (!(cachep->flags & SLAB_DEBUG_OBJECTS))
+               debug_check_no_obj_freed(objp, obj_size(cachep));
        __cache_free(cachep, objp);
        local_irq_restore(flags);
 }
@@ -3785,6 +3790,7 @@ void kfree(const void *objp)
        kfree_debugcheck(objp);
        c = virt_to_cache(objp);
        debug_check_no_locks_freed(objp, obj_size(c));
+       debug_check_no_obj_freed(objp, obj_size(c));
        __cache_free(c, (void *)objp);
        local_irq_restore(flags);
 }
index 992ecd4f0d393c748dceec95e3ddd714b16557b4..70db2897c1ea626ea3b6f576fda91fa6c3c48cd9 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -19,6 +19,7 @@
 #include <linux/cpuset.h>
 #include <linux/mempolicy.h>
 #include <linux/ctype.h>
+#include <linux/debugobjects.h>
 #include <linux/kallsyms.h>
 #include <linux/memory.h>
 
@@ -1747,6 +1748,8 @@ static __always_inline void slab_free(struct kmem_cache *s,
        local_irq_save(flags);
        c = get_cpu_slab(s, smp_processor_id());
        debug_check_no_locks_freed(object, c->objsize);
+       if (!(s->flags & SLAB_DEBUG_OBJECTS))
+               debug_check_no_obj_freed(object, s->objsize);
        if (likely(page == c->page && c->node >= 0)) {
                object[c->offset] = c->freelist;
                c->freelist = object;
@@ -2978,7 +2981,7 @@ void __init kmem_cache_init(void)
        kmalloc_caches[0].refcount = -1;
        caches++;
 
-       hotplug_memory_notifier(slab_memory_callback, 1);
+       hotplug_memory_notifier(slab_memory_callback, SLAB_CALLBACK_PRI);
 #endif
 
        /* Able to allocate the per node structures */
index dff71f173ae9cbfc1c82a2894990efd8c27aa43e..36511c7b5e2c797067ccb539646f580aa8ec1012 100644 (file)
@@ -250,29 +250,18 @@ static unsigned long *__kmalloc_section_usemap(void)
 
 static unsigned long *__init sparse_early_usemap_alloc(unsigned long pnum)
 {
-       unsigned long *usemap, section_nr;
+       unsigned long *usemap;
        struct mem_section *ms = __nr_to_section(pnum);
        int nid = sparse_early_nid(ms);
-       struct pglist_data *pgdat = NODE_DATA(nid);
 
-       /*
-        * Usemap's page can't be freed until freeing other sections
-        * which use it. And, Pgdat has same feature.
-        * If section A has pgdat and section B has usemap for other
-        * sections (includes section A), both sections can't be removed,
-        * because there is the dependency each other.
-        * To solve above issue, this collects all usemap on the same section
-        * which has pgdat.
-        */
-       section_nr = pfn_to_section_nr(__pa(pgdat) >> PAGE_SHIFT);
-       usemap = alloc_bootmem_section(usemap_size(), section_nr);
+       usemap = alloc_bootmem_node(NODE_DATA(nid), usemap_size());
        if (usemap)
                return usemap;
 
        /* Stupid: suppress gcc warning for SPARSEMEM && !NUMA */
        nid = 0;
 
-       printk(KERN_WARNING "%s: allocation failed\n", __FUNCTION__);
+       printk(KERN_WARNING "%s: allocation failed\n", __func__);
        return NULL;
 }
 
@@ -302,7 +291,7 @@ struct page __init *sparse_early_mem_map_alloc(unsigned long pnum)
                return map;
 
        printk(KERN_ERR "%s: sparsemem memory map backing failed "
-                       "some memory will not be available.\n", __FUNCTION__);
+                       "some memory will not be available.\n", __func__);
        ms->section_mem_map = 0;
        return NULL;
 }
index 50757ee3f9f3ee243ad23df60ae56a923bb0e64e..d8aadaf2a0baa5e87aff579039323585add00952 100644 (file)
@@ -33,7 +33,7 @@ static const struct address_space_operations swap_aops = {
 };
 
 static struct backing_dev_info swap_backing_dev_info = {
-       .capabilities   = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
+       .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK,
        .unplug_io_fn   = swap_unplug_io_fn,
 };
 
index 67051be7083a090be8bc08b80111a1126cfa5242..bd1bb59203065621e561900b125c017bfe65054d 100644 (file)
@@ -1426,11 +1426,7 @@ static const struct file_operations proc_swaps_operations = {
 
 static int __init procswaps_init(void)
 {
-       struct proc_dir_entry *entry;
-
-       entry = create_proc_entry("swaps", 0, NULL);
-       if (entry)
-               entry->proc_fops = &proc_swaps_operations;
+       proc_create("swaps", 0, NULL, &proc_swaps_operations);
        return 0;
 }
 __initcall(procswaps_init);
index e33e0ae69ad142d6241921d64cfaed37abfdb51a..2a39cf128aba2a7a583501a6686d9214070eb7bd 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/seq_file.h>
+#include <linux/debugobjects.h>
 #include <linux/vmalloc.h>
 #include <linux/kallsyms.h>
 
@@ -394,6 +395,7 @@ static void __vunmap(const void *addr, int deallocate_pages)
        }
 
        debug_check_no_locks_freed(addr, area->size);
+       debug_check_no_obj_freed(addr, area->size);
 
        if (deallocate_pages) {
                int i;
index eceac9f9032fda78ffd2f79a44f95b4f33762a0f..9a29901ad3b3474858d94f1e281306645f5fc297 100644 (file)
@@ -191,7 +191,7 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
                shrinker->nr += delta;
                if (shrinker->nr < 0) {
                        printk(KERN_ERR "%s: nr=%ld\n",
-                                       __FUNCTION__, shrinker->nr);
+                                       __func__, shrinker->nr);
                        shrinker->nr = max_pass;
                }
 
@@ -339,7 +339,7 @@ static pageout_t pageout(struct page *page, struct address_space *mapping,
                if (PagePrivate(page)) {
                        if (try_to_free_buffers(page)) {
                                ClearPageDirty(page);
-                               printk("%s: orphaned page\n", __FUNCTION__);
+                               printk("%s: orphaned page\n", __func__);
                                return PAGE_CLEAN;
                        }
                }
@@ -1299,6 +1299,9 @@ static unsigned long shrink_zones(int priority, struct zonelist *zonelist,
  * hope that some of these pages can be written.  But if the allocating task
  * holds filesystem locks which prevent writeout this might not work, and the
  * allocation attempt will fail.
+ *
+ * returns:    0, if no pages reclaimed
+ *             else, the number of pages reclaimed
  */
 static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
                                        struct scan_control *sc)
@@ -1347,7 +1350,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
                }
                total_scanned += sc->nr_scanned;
                if (nr_reclaimed >= sc->swap_cluster_max) {
-                       ret = 1;
+                       ret = nr_reclaimed;
                        goto out;
                }
 
@@ -1370,7 +1373,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
        }
        /* top priority shrink_caches still had more to do? don't OOM, then */
        if (!sc->all_unreclaimable && scan_global_lru(sc))
-               ret = 1;
+               ret = nr_reclaimed;
 out:
        /*
         * Now that we've scanned all the zones at this priority level, note
index ec6035eda933f463ceaa849e8f9f96663a2a025f..1a32130b958c418ec8a018aa676c73bb3d7cde32 100644 (file)
@@ -548,6 +548,10 @@ static int pagetypeinfo_show(struct seq_file *m, void *arg)
 {
        pg_data_t *pgdat = (pg_data_t *)arg;
 
+       /* check memoryless node */
+       if (!node_state(pgdat->node_id, N_HIGH_MEMORY))
+               return 0;
+
        seq_printf(m, "Page block order: %d\n", pageblock_order);
        seq_printf(m, "Pages per block:  %lu\n", pageblock_nr_pages);
        seq_putc(m, '\n');
@@ -608,6 +612,7 @@ static const char * const vmstat_text[] = {
        "nr_unstable",
        "nr_bounce",
        "nr_vmscan_write",
+       "nr_writeback_temp",
 
 #ifdef CONFIG_NUMA
        "numa_hit",
index e1df1ab3e04a18d32f9f4aa3fe86e42a9737e3cd..ed49da592051f368cf32b3bafd59bd05494c3c67 100644 (file)
@@ -1524,7 +1524,7 @@ static int dev_gso_segment(struct sk_buff *skb)
        if (!segs)
                return 0;
 
-       if (unlikely(IS_ERR(segs)))
+       if (IS_ERR(segs))
                return PTR_ERR(segs);
 
        skb->next = segs;
index f2b5270efdaaa4e056cff85624662fc853e79775..24eca23c2db3159c91898bd7fefe8bbb501f1233 100644 (file)
@@ -1234,7 +1234,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
                segs = ops->gso_segment(skb, features);
        rcu_read_unlock();
 
-       if (!segs || unlikely(IS_ERR(segs)))
+       if (!segs || IS_ERR(segs))
                goto out;
 
        skb = segs;
index d2620410cb0aa1215c2e60682f215618466e069f..76c3057d01790c23ae1e1055e6927cf6c2d2a6a0 100644 (file)
@@ -555,10 +555,8 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
 
        ircomm_tty_shutdown(self);
 
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
-       if (tty->ldisc.flush_buffer)
-               tty->ldisc.flush_buffer(tty);
+       tty_driver_flush_buffer(tty);
+       tty_ldisc_flush(tty);
 
        tty->closing = 0;
        self->tty = NULL;
index a4f1439ffdd8b80a4d5847121abe041adeba7627..75497e55927d695a3eee228833c68097edeb86ae 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include "irnet_irda.h"                /* Private header */
+#include <linux/seq_file.h>
 
 /*
  * PPP disconnect work: we need to make sure we're in
@@ -1717,34 +1718,23 @@ irnet_expiry_indication(discinfo_t *    expiry,
  */
 
 #ifdef CONFIG_PROC_FS
-/*------------------------------------------------------------------*/
-/*
- * Function irnet_proc_read (buf, start, offset, len, unused)
- *
- *    Give some info to the /proc file system
- */
 static int
-irnet_proc_read(char * buf,
-               char ** start,
-               off_t   offset,
-               int     len)
+irnet_proc_show(struct seq_file *m, void *v)
 {
   irnet_socket *       self;
   char *               state;
   int                  i = 0;
 
-  len = 0;
-
   /* Get the IrNET server information... */
-  len += sprintf(buf+len, "IrNET server - ");
-  len += sprintf(buf+len, "IrDA state: %s, ",
+  seq_printf(m, "IrNET server - ");
+  seq_printf(m, "IrDA state: %s, ",
                 (irnet_server.running ? "running" : "dead"));
-  len += sprintf(buf+len, "stsap_sel: %02x, ", irnet_server.s.stsap_sel);
-  len += sprintf(buf+len, "dtsap_sel: %02x\n", irnet_server.s.dtsap_sel);
+  seq_printf(m, "stsap_sel: %02x, ", irnet_server.s.stsap_sel);
+  seq_printf(m, "dtsap_sel: %02x\n", irnet_server.s.dtsap_sel);
 
   /* Do we need to continue ? */
   if(!irnet_server.running)
-    return len;
+    return 0;
 
   /* Protect access to the instance list */
   spin_lock_bh(&irnet_server.spinlock);
@@ -1754,23 +1744,23 @@ irnet_proc_read(char *  buf,
   while(self != NULL)
     {
       /* Start printing info about the socket. */
-      len += sprintf(buf+len, "\nIrNET socket %d - ", i++);
+      seq_printf(m, "\nIrNET socket %d - ", i++);
 
       /* First, get the requested configuration */
-      len += sprintf(buf+len, "Requested IrDA name: \"%s\", ", self->rname);
-      len += sprintf(buf+len, "daddr: %08x, ", self->rdaddr);
-      len += sprintf(buf+len, "saddr: %08x\n", self->rsaddr);
+      seq_printf(m, "Requested IrDA name: \"%s\", ", self->rname);
+      seq_printf(m, "daddr: %08x, ", self->rdaddr);
+      seq_printf(m, "saddr: %08x\n", self->rsaddr);
 
       /* Second, get all the PPP info */
-      len += sprintf(buf+len, "        PPP state: %s",
+      seq_printf(m, "  PPP state: %s",
                 (self->ppp_open ? "registered" : "unregistered"));
       if(self->ppp_open)
        {
-         len += sprintf(buf+len, ", unit: ppp%d",
+         seq_printf(m, ", unit: ppp%d",
                         ppp_unit_number(&self->chan));
-         len += sprintf(buf+len, ", channel: %d",
+         seq_printf(m, ", channel: %d",
                         ppp_channel_index(&self->chan));
-         len += sprintf(buf+len, ", mru: %d",
+         seq_printf(m, ", mru: %d",
                         self->mru);
          /* Maybe add self->flags ? Later... */
        }
@@ -1789,10 +1779,10 @@ irnet_proc_read(char *  buf,
              state = "weird";
            else
              state = "idle";
-      len += sprintf(buf+len, "\n      IrDA state: %s, ", state);
-      len += sprintf(buf+len, "daddr: %08x, ", self->daddr);
-      len += sprintf(buf+len, "stsap_sel: %02x, ", self->stsap_sel);
-      len += sprintf(buf+len, "dtsap_sel: %02x\n", self->dtsap_sel);
+      seq_printf(m, "\n        IrDA state: %s, ", state);
+      seq_printf(m, "daddr: %08x, ", self->daddr);
+      seq_printf(m, "stsap_sel: %02x, ", self->stsap_sel);
+      seq_printf(m, "dtsap_sel: %02x\n", self->dtsap_sel);
 
       /* Next socket, please... */
       self = (irnet_socket *) hashbin_get_next(irnet_server.list);
@@ -1801,8 +1791,21 @@ irnet_proc_read(char *   buf,
   /* Spin lock end */
   spin_unlock_bh(&irnet_server.spinlock);
 
-  return len;
+  return 0;
 }
+
+static int irnet_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, irnet_proc_show, NULL);
+}
+
+static const struct file_operations irnet_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = irnet_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
 #endif /* PROC_FS */
 
 
@@ -1841,7 +1844,7 @@ irda_irnet_init(void)
 
 #ifdef CONFIG_PROC_FS
   /* Add a /proc file for irnet infos */
-  create_proc_info_entry("irnet", 0, proc_irda, irnet_proc_read);
+  proc_create("irnet", 0, proc_irda, &irnet_proc_fops);
 #endif /* CONFIG_PROC_FS */
 
   /* Setup the IrNET server */
index 0ba92d0d52040e6c142dd7a1184d6cb44e87dde7..3e408952a3f178ce98f36da48b400d0d8ec6a8e6 100644 (file)
@@ -159,14 +159,6 @@ static void
                                DISCOVERY_MODE,
                                void *);
 #endif
-/* -------------------------- PROC ENTRY -------------------------- */
-#ifdef CONFIG_PROC_FS
-static int
-       irnet_proc_read(char *,
-                       char **,
-                       off_t,
-                       int);
-#endif /* CONFIG_PROC_FS */
 
 /**************************** VARIABLES ****************************/
 
index 2403a31fe0f64ea6de774982e2ba3c6b7ea36a35..9e7236ff6bcc029e6886b43c32416bcdaa51d252 100644 (file)
@@ -1498,7 +1498,8 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
                err = xfrm_state_update(x);
 
        xfrm_audit_state_add(x, err ? 0 : 1,
-                            audit_get_loginuid(current), 0);
+                            audit_get_loginuid(current),
+                            audit_get_sessionid(current), 0);
 
        if (err < 0) {
                x->km.state = XFRM_STATE_DEAD;
@@ -1552,7 +1553,8 @@ static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
        km_state_notify(x, &c);
 out:
        xfrm_audit_state_delete(x, err ? 0 : 1,
-                              audit_get_loginuid(current), 0);
+                               audit_get_loginuid(current),
+                               audit_get_sessionid(current), 0);
        xfrm_state_put(x);
 
        return err;
@@ -1728,6 +1730,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd
                return -EINVAL;
 
        audit_info.loginuid = audit_get_loginuid(current);
+       audit_info.sessionid = audit_get_sessionid(current);
        audit_info.secid = 0;
        err = xfrm_state_flush(proto, &audit_info);
        if (err)
@@ -2324,7 +2327,8 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
                                 hdr->sadb_msg_type != SADB_X_SPDUPDATE);
 
        xfrm_audit_policy_add(xp, err ? 0 : 1,
-                            audit_get_loginuid(current), 0);
+                             audit_get_loginuid(current),
+                             audit_get_sessionid(current), 0);
 
        if (err)
                goto out;
@@ -2406,7 +2410,8 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
                return -ENOENT;
 
        xfrm_audit_policy_delete(xp, err ? 0 : 1,
-                               audit_get_loginuid(current), 0);
+                                audit_get_loginuid(current),
+                                audit_get_sessionid(current), 0);
 
        if (err)
                goto out;
@@ -2667,7 +2672,8 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
 
        if (delete) {
                xfrm_audit_policy_delete(xp, err ? 0 : 1,
-                               audit_get_loginuid(current), 0);
+                               audit_get_loginuid(current),
+                               audit_get_sessionid(current), 0);
 
                if (err)
                        goto out;
@@ -2767,6 +2773,7 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg
        int err;
 
        audit_info.loginuid = audit_get_loginuid(current);
+       audit_info.sessionid = audit_get_sessionid(current);
        audit_info.secid = 0;
        err = xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info);
        if (err)
index bbd26893c0c4f7e46d1c312eeaed743b7834f5be..582ec3efc8a55f32603feeca879a8267a2639d6b 100644 (file)
@@ -214,7 +214,7 @@ int nf_queue(struct sk_buff *skb,
 
        segs = skb_gso_segment(skb, 0);
        kfree_skb(skb);
-       if (unlikely(IS_ERR(segs)))
+       if (IS_ERR(segs))
                return 1;
 
        do {
index d282ad1570a77482a58b836065f79e3ae2714a61..0099da5b2591e5295429b7578688fa6949db3db1 100644 (file)
@@ -1780,6 +1780,7 @@ int __init netlbl_unlabel_defconf(void)
         * messages so don't worry to much about these values. */
        security_task_getsecid(current, &audit_info.secid);
        audit_info.loginuid = 0;
+       audit_info.sessionid = 0;
 
        entry = kzalloc(sizeof(*entry), GFP_KERNEL);
        if (entry == NULL)
index b17d4203806e2102812bcd4cbe4754340cde9395..68706b4e3bf8a5d800510854a074537c762cf73d 100644 (file)
@@ -107,7 +107,9 @@ struct audit_buffer *netlbl_audit_start_common(int type,
        if (audit_buf == NULL)
                return NULL;
 
-       audit_log_format(audit_buf, "netlabel: auid=%u", audit_info->loginuid);
+       audit_log_format(audit_buf, "netlabel: auid=%u ses=%u",
+                        audit_info->loginuid,
+                        audit_info->sessionid);
 
        if (audit_info->secid != 0 &&
            security_secid_to_secctx(audit_info->secid,
index 6d7f4ab46c2bd7499d726eac6b5190332e87e69c..6caef8b20611c55443fb1d4617f33cebfa42d835 100644 (file)
@@ -51,6 +51,7 @@ static inline void netlbl_netlink_auditinfo(struct sk_buff *skb,
 {
        audit_info->secid = NETLINK_CB(skb).sid;
        audit_info->loginuid = NETLINK_CB(skb).loginuid;
+       audit_info->sessionid = NETLINK_CB(skb).sessionid;
 }
 
 /* NetLabel NETLINK I/O functions */
index 46f3e44bb83a583bbacfc4d84765082aaee7f4e8..9b97f8006c9c6edfd0dea0dde522b6a7e64c171f 100644 (file)
@@ -1248,6 +1248,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
        NETLINK_CB(skb).pid     = nlk->pid;
        NETLINK_CB(skb).dst_group = dst_group;
        NETLINK_CB(skb).loginuid = audit_get_loginuid(current);
+       NETLINK_CB(skb).sessionid = audit_get_sessionid(current);
        security_task_getsecid(current, &(NETLINK_CB(skb).sid));
        memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
 
index 2519129c6d213f85bceebc165e2c27744f2fd3b6..09cd9c0c2d805bcac6f742d5a3ef8945502fe223 100644 (file)
@@ -150,7 +150,7 @@ static int xfrm_output_gso(struct sk_buff *skb)
 
        segs = skb_gso_segment(skb, 0);
        kfree_skb(skb);
-       if (unlikely(IS_ERR(segs)))
+       if (IS_ERR(segs))
                return PTR_ERR(segs);
 
        do {
index e0c0390613c0bca03920328ae2ad77052a22ecff..cae9fd81554350eb1893aa1da37ada7f646b5a08 100644 (file)
@@ -762,6 +762,7 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
                        if (err) {
                                xfrm_audit_policy_delete(pol, 0,
                                                         audit_info->loginuid,
+                                                        audit_info->sessionid,
                                                         audit_info->secid);
                                return err;
                        }
@@ -777,6 +778,7 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
                                if (err) {
                                        xfrm_audit_policy_delete(pol, 0,
                                                        audit_info->loginuid,
+                                                       audit_info->sessionid,
                                                        audit_info->secid);
                                        return err;
                                }
@@ -819,6 +821,7 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
                        write_unlock_bh(&xfrm_policy_lock);
 
                        xfrm_audit_policy_delete(pol, 1, audit_info->loginuid,
+                                                audit_info->sessionid,
                                                 audit_info->secid);
 
                        xfrm_policy_kill(pol);
@@ -841,6 +844,7 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
 
                                xfrm_audit_policy_delete(pol, 1,
                                                         audit_info->loginuid,
+                                                        audit_info->sessionid,
                                                         audit_info->secid);
                                xfrm_policy_kill(pol);
                                killed++;
@@ -2472,14 +2476,14 @@ static void xfrm_audit_common_policyinfo(struct xfrm_policy *xp,
 }
 
 void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
-                          u32 auid, u32 secid)
+                          uid_t auid, u32 sessionid, u32 secid)
 {
        struct audit_buffer *audit_buf;
 
        audit_buf = xfrm_audit_start("SPD-add");
        if (audit_buf == NULL)
                return;
-       xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
+       xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf);
        audit_log_format(audit_buf, " res=%u", result);
        xfrm_audit_common_policyinfo(xp, audit_buf);
        audit_log_end(audit_buf);
@@ -2487,14 +2491,14 @@ void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
 EXPORT_SYMBOL_GPL(xfrm_audit_policy_add);
 
 void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result,
-                             u32 auid, u32 secid)
+                             uid_t auid, u32 sessionid, u32 secid)
 {
        struct audit_buffer *audit_buf;
 
        audit_buf = xfrm_audit_start("SPD-delete");
        if (audit_buf == NULL)
                return;
-       xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
+       xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf);
        audit_log_format(audit_buf, " res=%u", result);
        xfrm_audit_common_policyinfo(xp, audit_buf);
        audit_log_end(audit_buf);
index fac27ce770d53d23653ac0418c281685542f963f..72fddafd891a0b3f3be603804e6c5727a56a5b3d 100644 (file)
@@ -496,7 +496,8 @@ expired:
                km_state_expired(x, 1, 0);
 
        xfrm_audit_state_delete(x, err ? 0 : 1,
-                               audit_get_loginuid(current), 0);
+                               audit_get_loginuid(current),
+                               audit_get_sessionid(current), 0);
 
 out:
        spin_unlock(&x->lock);
@@ -603,6 +604,7 @@ xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info)
                           (err = security_xfrm_state_delete(x)) != 0) {
                                xfrm_audit_state_delete(x, 0,
                                                        audit_info->loginuid,
+                                                       audit_info->sessionid,
                                                        audit_info->secid);
                                return err;
                        }
@@ -641,6 +643,7 @@ restart:
                                err = xfrm_state_delete(x);
                                xfrm_audit_state_delete(x, err ? 0 : 1,
                                                        audit_info->loginuid,
+                                                       audit_info->sessionid,
                                                        audit_info->secid);
                                xfrm_state_put(x);
 
@@ -2123,14 +2126,14 @@ static void xfrm_audit_helper_pktinfo(struct sk_buff *skb, u16 family,
 }
 
 void xfrm_audit_state_add(struct xfrm_state *x, int result,
-                         u32 auid, u32 secid)
+                         uid_t auid, u32 sessionid, u32 secid)
 {
        struct audit_buffer *audit_buf;
 
        audit_buf = xfrm_audit_start("SAD-add");
        if (audit_buf == NULL)
                return;
-       xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
+       xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf);
        xfrm_audit_helper_sainfo(x, audit_buf);
        audit_log_format(audit_buf, " res=%u", result);
        audit_log_end(audit_buf);
@@ -2138,14 +2141,14 @@ void xfrm_audit_state_add(struct xfrm_state *x, int result,
 EXPORT_SYMBOL_GPL(xfrm_audit_state_add);
 
 void xfrm_audit_state_delete(struct xfrm_state *x, int result,
-                            u32 auid, u32 secid)
+                            uid_t auid, u32 sessionid, u32 secid)
 {
        struct audit_buffer *audit_buf;
 
        audit_buf = xfrm_audit_start("SAD-delete");
        if (audit_buf == NULL)
                return;
-       xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
+       xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf);
        xfrm_audit_helper_sainfo(x, audit_buf);
        audit_log_format(audit_buf, " res=%u", result);
        audit_log_end(audit_buf);
index 22a30ae582a2738cc8453fcdefe1893caa1b6263..a1b0fbe3ea351f6e7e953078ffd90d29dd29e196 100644 (file)
@@ -407,6 +407,9 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
        struct xfrm_state *x;
        int err;
        struct km_event c;
+       uid_t loginuid = NETLINK_CB(skb).loginuid;
+       u32 sessionid = NETLINK_CB(skb).sessionid;
+       u32 sid = NETLINK_CB(skb).sid;
 
        err = verify_newsa_info(p, attrs);
        if (err)
@@ -422,8 +425,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
        else
                err = xfrm_state_update(x);
 
-       xfrm_audit_state_add(x, err ? 0 : 1, NETLINK_CB(skb).loginuid,
-                            NETLINK_CB(skb).sid);
+       xfrm_audit_state_add(x, err ? 0 : 1, loginuid, sessionid, sid);
 
        if (err < 0) {
                x->km.state = XFRM_STATE_DEAD;
@@ -478,6 +480,9 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
        int err = -ESRCH;
        struct km_event c;
        struct xfrm_usersa_id *p = nlmsg_data(nlh);
+       uid_t loginuid = NETLINK_CB(skb).loginuid;
+       u32 sessionid = NETLINK_CB(skb).sessionid;
+       u32 sid = NETLINK_CB(skb).sid;
 
        x = xfrm_user_state_lookup(p, attrs, &err);
        if (x == NULL)
@@ -502,8 +507,7 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
        km_state_notify(x, &c);
 
 out:
-       xfrm_audit_state_delete(x, err ? 0 : 1, NETLINK_CB(skb).loginuid,
-                               NETLINK_CB(skb).sid);
+       xfrm_audit_state_delete(x, err ? 0 : 1, loginuid, sessionid, sid);
        xfrm_state_put(x);
        return err;
 }
@@ -1123,6 +1127,9 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
        struct km_event c;
        int err;
        int excl;
+       uid_t loginuid = NETLINK_CB(skb).loginuid;
+       u32 sessionid = NETLINK_CB(skb).sessionid;
+       u32 sid = NETLINK_CB(skb).sid;
 
        err = verify_newpolicy_info(p);
        if (err)
@@ -1141,8 +1148,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
         * a type XFRM_MSG_UPDPOLICY - JHS */
        excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY;
        err = xfrm_policy_insert(p->dir, xp, excl);
-       xfrm_audit_policy_add(xp, err ? 0 : 1, NETLINK_CB(skb).loginuid,
-                             NETLINK_CB(skb).sid);
+       xfrm_audit_policy_add(xp, err ? 0 : 1, loginuid, sessionid, sid);
 
        if (err) {
                security_xfrm_policy_free(xp->security);
@@ -1371,9 +1377,12 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
                                            NETLINK_CB(skb).pid);
                }
        } else {
-               xfrm_audit_policy_delete(xp, err ? 0 : 1,
-                                        NETLINK_CB(skb).loginuid,
-                                        NETLINK_CB(skb).sid);
+               uid_t loginuid = NETLINK_CB(skb).loginuid;
+               u32 sessionid = NETLINK_CB(skb).sessionid;
+               u32 sid = NETLINK_CB(skb).sid;
+
+               xfrm_audit_policy_delete(xp, err ? 0 : 1, loginuid, sessionid,
+                                        sid);
 
                if (err != 0)
                        goto out;
@@ -1399,6 +1408,7 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
        int err;
 
        audit_info.loginuid = NETLINK_CB(skb).loginuid;
+       audit_info.sessionid = NETLINK_CB(skb).sessionid;
        audit_info.secid = NETLINK_CB(skb).sid;
        err = xfrm_state_flush(p->proto, &audit_info);
        if (err)
@@ -1546,6 +1556,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
                return err;
 
        audit_info.loginuid = NETLINK_CB(skb).loginuid;
+       audit_info.sessionid = NETLINK_CB(skb).sessionid;
        audit_info.secid = NETLINK_CB(skb).sid;
        err = xfrm_policy_flush(type, &audit_info);
        if (err)
@@ -1604,9 +1615,11 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
        read_unlock(&xp->lock);
        err = 0;
        if (up->hard) {
+               uid_t loginuid = NETLINK_CB(skb).loginuid;
+               uid_t sessionid = NETLINK_CB(skb).sessionid;
+               u32 sid = NETLINK_CB(skb).sid;
                xfrm_policy_delete(xp, p->dir);
-               xfrm_audit_policy_delete(xp, 1, NETLINK_CB(skb).loginuid,
-                                        NETLINK_CB(skb).sid);
+               xfrm_audit_policy_delete(xp, 1, loginuid, sessionid, sid);
 
        } else {
                // reset the timers here?
@@ -1640,9 +1653,11 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
        km_state_expired(x, ue->hard, current->pid);
 
        if (ue->hard) {
+               uid_t loginuid = NETLINK_CB(skb).loginuid;
+               uid_t sessionid = NETLINK_CB(skb).sessionid;
+               u32 sid = NETLINK_CB(skb).sid;
                __xfrm_state_delete(x);
-               xfrm_audit_state_delete(x, 1, NETLINK_CB(skb).loginuid,
-                                       NETLINK_CB(skb).sid);
+               xfrm_audit_state_delete(x, 1, loginuid, sessionid, sid);
        }
        err = 0;
 out:
index 05e438f8b4e2d8511e69a4961cf8e35b0dbbeebd..e90dc5d04392dcc0f10d6d480dd6a866cc54df0e 100644 (file)
@@ -33,10 +33,8 @@ static struct file_operations mark_ops = {
 static int example_init(void)
 {
        printk(KERN_ALERT "example init\n");
-       pentry_example = create_proc_entry("marker-example", 0444, NULL);
-       if (pentry_example)
-               pentry_example->proc_fops = &mark_ops;
-       else
+       pentry_example = proc_create("marker-example", 0444, NULL, &mark_ops);
+       if (!pentry_example)
                return -EPERM;
        return 0;
 }
index 9468ec7971db933e2594171ff66c8dd17c9368c8..9c4b3e2b7098a9d2af14c50614189c9a28cd689b 100755 (executable)
@@ -1,2 +1,18 @@
 #!/bin/sh
-indent -npro -kr -i8 -ts8 -sob -l80 -ss -ncs -cp1 "$@"
+PARAM="-npro -kr -i8 -ts8 -sob -l80 -ss -ncs -cp1"
+RES=`indent --version`
+V1=`echo $RES | cut -d' ' -f3 | cut -d'.' -f1`
+V2=`echo $RES | cut -d' ' -f3 | cut -d'.' -f2`
+V3=`echo $RES | cut -d' ' -f3 | cut -d'.' -f3`
+if [ $V1 -gt 2 ]; then
+  PARAM="$PARAM -il0"
+elif [ $V1 -eq 2 ]; then
+  if [ $V2 -gt 2 ]; then
+    PARAM="$PARAM -il0";
+  elif [ $V2 -eq 2 ]; then
+    if [ $V3 -ge 10 ]; then
+      PARAM="$PARAM -il0"
+    fi
+  fi
+fi
+indent $PARAM "$@"
index 64ec4b8a51b502cca0b37638f4443813d65d35ae..b6bbbcdc557eb05d7eeb55f11887a34915f722b1 100755 (executable)
@@ -9,7 +9,7 @@ use strict;
 my $P = $0;
 $P =~ s@.*/@@g;
 
-my $V = '0.16';
+my $V = '0.18';
 
 use Getopt::Long qw(:config no_auto_abbrev);
 
@@ -131,6 +131,17 @@ our $NonptrType;
 our $Type;
 our $Declare;
 
+our $UTF8      = qr {
+       [\x09\x0A\x0D\x20-\x7E]              # ASCII
+       | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
+       |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
+       | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
+       |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
+       |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
+       | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
+       |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
+}x;
+
 our @typeList = (
        qr{void},
        qr{char},
@@ -692,7 +703,7 @@ sub annotate_values {
        while (length($cur)) {
                @av_paren_type = ('E') if ($#av_paren_type < 0);
                print " <" . join('', @av_paren_type) .
-                                       "> <$type> " if ($dbg_values > 1);
+                               "> <$type> <$av_pending>" if ($dbg_values > 1);
                if ($cur =~ /^(\s+)/o) {
                        print "WS($1)\n" if ($dbg_values > 1);
                        if ($1 =~ /\n/ && $av_preprocessor) {
@@ -705,9 +716,18 @@ sub annotate_values {
                        $type = 'T';
 
                } elsif ($cur =~ /^(#\s*define\s*$Ident)(\(?)/o) {
-                       print "DEFINE($1)\n" if ($dbg_values > 1);
+                       print "DEFINE($1,$2)\n" if ($dbg_values > 1);
                        $av_preprocessor = 1;
-                       $av_pending = 'N';
+                       push(@av_paren_type, $type);
+                       if ($2 ne '') {
+                               $av_pending = 'N';
+                       }
+                       $type = 'E';
+
+               } elsif ($cur =~ /^(#\s*undef\s*$Ident)/o) {
+                       print "UNDEF($1)\n" if ($dbg_values > 1);
+                       $av_preprocessor = 1;
+                       push(@av_paren_type, $type);
 
                } elsif ($cur =~ /^(#\s*(?:ifdef|ifndef|if))/o) {
                        print "PRE_START($1)\n" if ($dbg_values > 1);
@@ -715,7 +735,7 @@ sub annotate_values {
 
                        push(@av_paren_type, $type);
                        push(@av_paren_type, $type);
-                       $type = 'N';
+                       $type = 'E';
 
                } elsif ($cur =~ /^(#\s*(?:else|elif))/o) {
                        print "PRE_RESTART($1)\n" if ($dbg_values > 1);
@@ -723,7 +743,7 @@ sub annotate_values {
 
                        push(@av_paren_type, $av_paren_type[$#av_paren_type]);
 
-                       $type = 'N';
+                       $type = 'E';
 
                } elsif ($cur =~ /^(#\s*(?:endif))/o) {
                        print "PRE_END($1)\n" if ($dbg_values > 1);
@@ -734,11 +754,16 @@ sub annotate_values {
                        # one does, and continue as if the #endif was not here.
                        pop(@av_paren_type);
                        push(@av_paren_type, $type);
-                       $type = 'N';
+                       $type = 'E';
 
                } elsif ($cur =~ /^(\\\n)/o) {
                        print "PRECONT($1)\n" if ($dbg_values > 1);
 
+               } elsif ($cur =~ /^(__attribute__)\s*\(?/o) {
+                       print "ATTR($1)\n" if ($dbg_values > 1);
+                       $av_pending = $type;
+                       $type = 'N';
+
                } elsif ($cur =~ /^(sizeof)\s*(\()?/o) {
                        print "SIZEOF($1)\n" if ($dbg_values > 1);
                        if (defined $2) {
@@ -930,7 +955,7 @@ sub process {
                        # edge is a close comment then we must be in a comment
                        # at context start.
                        my $edge;
-                       for (my $ln = $linenr; $ln < ($linenr + $realcnt); $ln++) {
+                       for (my $ln = $linenr + 1; $ln < ($linenr + $realcnt); $ln++) {
                                next if ($line =~ /^-/);
                                ($edge) = ($rawlines[$ln - 1] =~ m@(/\*|\*/)@);
                                last if (defined $edge);
@@ -951,9 +976,9 @@ sub process {
                        ##print "COMMENT:$in_comment edge<$edge> $rawline\n";
                        sanitise_line_reset($in_comment);
 
-               } elsif ($realcnt) {
+               } elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) {
                        # Standardise the strings and chars within the input to
-                       # simplify matching.
+                       # simplify matching -- only bother with positive lines.
                        $line = sanitise_line($rawline);
                }
                push(@lines, $line);
@@ -1066,17 +1091,14 @@ sub process {
 
 # UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
                if (($realfile =~ /^$/ || $line =~ /^\+/) &&
-                    !($rawline =~ m/^(
-                               [\x09\x0A\x0D\x20-\x7E]              # ASCII
-                               | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
-                               |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
-                               | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
-                               |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
-                               |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
-                               | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
-                               |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
-                               )*$/x )) {
-                       ERROR("Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $herecurr);
+                   $rawline !~ m/^$UTF8*$/) {
+                       my ($utf8_prefix) = ($rawline =~ /^($UTF8*)/);
+
+                       my $blank = copy_spacing($rawline);
+                       my $ptr = substr($blank, 0, length($utf8_prefix)) . "^";
+                       my $hereptr = "$hereline$ptr\n";
+
+                       ERROR("Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr);
                }
 
 #ignore lines being removed
@@ -1112,7 +1134,7 @@ sub process {
                if ($rawline =~ /^\+\s* \t\s*\S/ ||
                    $rawline =~ /^\+\s*        \s*/) {
                        my $herevet = "$here\n" . cat_vet($rawline) . "\n";
-                       ERROR("use tabs not spaces\n" . $herevet);
+                       ERROR("code indent should use tabs where possible\n" . $herevet);
                }
 
 # check for RCS/CVS revision markers
@@ -1121,35 +1143,40 @@ sub process {
                }
 
 # Check for potential 'bare' types
-               if ($realcnt) {
-                       my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0);
-                       $s =~ s/\n./ /g;
-                       $s =~ s/{.*$//;
+               my ($stat, $cond);
+               if ($realcnt && $line =~ /.\s*\S/) {
+                       ($stat, $cond) = ctx_statement_block($linenr,
+                                                               $realcnt, 0);
+                       $stat =~ s/\n./\n /g;
+                       $cond =~ s/\n./\n /g;
+
+                       my $s = $stat;
+                       $s =~ s/{.*$//s;
 
                        # Ignore goto labels.
-                       if ($s =~ /$Ident:\*$/) {
+                       if ($s =~ /$Ident:\*$/s) {
 
                        # Ignore functions being called
-                       } elsif ($s =~ /^.\s*$Ident\s*\(/) {
+                       } elsif ($s =~ /^.\s*$Ident\s*\(/s) {
 
                        # definitions in global scope can only start with types
-                       } elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b/) {
+                       } elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b/s) {
                                possible($1, $s);
 
                        # declarations always start with types
-                       } elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:const\s+)?($Ident)\b(:?\s+$Sparse)?\s*\**\s*$Ident\s*(?:;|=|,)/) {
+                       } elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:const\s+)?($Ident)\b(:?\s+$Sparse)?\s*\**\s*$Ident\s*(?:;|=|,)/s) {
                                possible($1, $s);
                        }
 
                        # any (foo ... *) is a pointer cast, and foo is a type
-                       while ($s =~ /\(($Ident)(?:\s+$Sparse)*\s*\*+\s*\)/g) {
+                       while ($s =~ /\(($Ident)(?:\s+$Sparse)*\s*\*+\s*\)/sg) {
                                possible($1, $s);
                        }
 
                        # Check for any sort of function declaration.
                        # int foo(something bar, other baz);
                        # void (*store_gdt)(x86_descr_ptr *);
-                       if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/) {
+                       if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s) {
                                my ($name_len) = length($1);
 
                                my $ctx = $s;
@@ -1282,18 +1309,19 @@ sub process {
                           ($prevline !~ /^ }/) &&
                           ($prevline !~ /^.DECLARE_$Ident\(\Q$name\E\)/) &&
                           ($prevline !~ /^.LIST_HEAD\(\Q$name\E\)/) &&
+                          ($prevline !~ /^.$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(/) &&
                           ($prevline !~ /\b\Q$name\E(?:\s+$Attribute)?\s*(?:;|=|\[)/)) {
                                WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
                        }
                }
 
 # check for external initialisers.
-               if ($line =~ /^.$Type\s*$Ident\s*=\s*(0|NULL);/) {
+               if ($line =~ /^.$Type\s*$Ident\s*=\s*(0|NULL|false)\s*;/) {
                        ERROR("do not initialise externals to 0 or NULL\n" .
                                $herecurr);
                }
 # check for static initialisers.
-               if ($line =~ /\s*static\s.*=\s*(0|NULL);/) {
+               if ($line =~ /\s*static\s.*=\s*(0|NULL|false)\s*;/) {
                        ERROR("do not initialise statics to 0 or NULL\n" .
                                $herecurr);
                }
@@ -1512,7 +1540,10 @@ sub process {
                                        if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
                                                ERROR("space required before that '$op' $at\n" . $hereptr);
                                        }
-                                       if ($ctx =~ /.xW/) {
+                                       if ($op  eq '*' && $cc =~/\s*const\b/) {
+                                               # A unary '*' may be const
+
+                                       } elsif ($ctx =~ /.xW/) {
                                                ERROR("space prohibited after that '$op' $at\n" . $hereptr);
                                        }
 
@@ -1617,7 +1648,7 @@ sub process {
 
 # Check for illegal assignment in if conditional.
                if ($line =~ /\bif\s*\(/) {
-                       my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0);
+                       my ($s, $c) = ($stat, $cond);
 
                        if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/) {
                                ERROR("do not use assignment in if condition\n" . $herecurr);
@@ -1695,7 +1726,7 @@ sub process {
 #warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line)
                if ($tree && $rawline =~ m{^.\#\s*include\s*\<asm\/(.*)\.h\>}) {
                        my $checkfile = "$root/include/linux/$1.h";
-                       if (-f $checkfile && $1 ne 'irq.h') {
+                       if (-f $checkfile && $1 ne 'irq') {
                                WARN("Use #include <linux/$1.h> instead of <asm/$1.h>\n" .
                                        $herecurr);
                        }
@@ -1910,7 +1941,8 @@ sub process {
                }
 
 # check for spinlock_t definitions without a comment.
-               if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/) {
+               if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ ||
+                   $line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) {
                        my $which = $1;
                        if (!ctx_has_comment($first_line, $linenr)) {
                                CHK("$1 definition without comment\n" . $herecurr);
@@ -1940,7 +1972,26 @@ sub process {
                }
 
 # check for new externs in .c files.
-               if ($line =~ /^.\s*extern\s/ && ($realfile =~ /\.c$/)) {
+               if ($realfile =~ /\.c$/ && defined $stat &&
+                   $stat =~ /^.\s*(?:extern\s+)?$Type\s+$Ident(\s*)\(/s)
+               {
+                       my $paren_space = $1;
+
+                       my $s = $stat;
+                       if (defined $cond) {
+                               substr($s, 0, length($cond), '');
+                       }
+                       if ($s =~ /^\s*;/) {
+                               WARN("externs should be avoided in .c files\n" .  $herecurr);
+                       }
+
+                       if ($paren_space =~ /\n/) {
+                               WARN("arguments for function declarations should follow identifier\n" . $herecurr);
+                       }
+
+               } elsif ($realfile =~ /\.c$/ && defined $stat &&
+                   $stat =~ /^.\s*extern\s+/)
+               {
                        WARN("externs should be avoided in .c files\n" .  $herecurr);
                }
 
@@ -1964,11 +2015,11 @@ sub process {
                }
 
 # check for semaphores used as mutexes
-               if ($line =~ /\b(DECLARE_MUTEX|init_MUTEX)\s*\(/) {
+               if ($line =~ /^.\s*(DECLARE_MUTEX|init_MUTEX)\s*\(/) {
                        WARN("mutexes are preferred for single holder semaphores\n" . $herecurr);
                }
 # check for semaphores used as mutexes
-               if ($line =~ /\binit_MUTEX_LOCKED\s*\(/) {
+               if ($line =~ /^.\s*init_MUTEX_LOCKED\s*\(/) {
                        WARN("consider using a completion\n" . $herecurr);
                }
 # recommend strict_strto* over simple_strto*
@@ -1979,11 +2030,24 @@ sub process {
 # use of NR_CPUS is usually wrong
 # ignore definitions of NR_CPUS and usage to define arrays as likely right
                if ($line =~ /\bNR_CPUS\b/ &&
-                   $line !~ /^.#\s*define\s+NR_CPUS\s+/ &&
-                   $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/)
+                   $line !~ /^.#\s*if\b.*\bNR_CPUS\b/ &&
+                   $line !~ /^.#\s*define\b.*\bNR_CPUS\b/ &&
+                   $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ &&
+                   $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ &&
+                   $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/)
                {
                        WARN("usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr);
                }
+
+# check for %L{u,d,i} in strings
+               my $string;
+               while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) {
+                       $string = substr($rawline, $-[1], $+[1] - $-[1]);
+                       if ($string =~ /(?<!%)%L[udi]/) {
+                               WARN("\%Ld/%Lu are not-standard C, use %lld/%llu\n" . $herecurr);
+                               last;
+                       }
+               }
        }
 
        # If we have no input at all, then there is nothing to report on
index c912137f80e247d0b8076e32f7386005127889a0..5d20a2e24cd1e18814483327645f25b6c2f73d0e 100644 (file)
@@ -7,12 +7,6 @@
  *
  * Usage: nm -n vmlinux | scripts/kallsyms [--all-symbols] > symbols.S
  *
- * ChangeLog:
- *
- * (25/Aug/2004) Paulo Marques <pmarques@grupopie.com>
- *      Changed the compression method from stem compression to "table lookup"
- *      compression
- *
  *      Table compression uses all the unused char codes on the symbols and
  *  maps these to the most used substrings (tokens). For instance, it might
  *  map char code 0xF7 to represent "write_" and then in every symbol where
index 769b69db89c13b6f6af68abbfe3167929d81d5e8..e04c4218cb5200d415a8933e84478e68b9cceee6 100644 (file)
@@ -576,6 +576,15 @@ static int do_virtio_entry(const char *filename, struct virtio_device_id *id,
        return 1;
 }
 
+/* Looks like: i2c:S */
+static int do_i2c_entry(const char *filename, struct i2c_device_id *id,
+                       char *alias)
+{
+       sprintf(alias, I2C_MODULE_PREFIX "%s", id->name);
+
+       return 1;
+}
+
 /* Ignore any prefix, eg. v850 prepends _ */
 static inline int sym_is(const char *symbol, const char *name)
 {
@@ -704,6 +713,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
                do_table(symval, sym->st_size,
                         sizeof(struct virtio_device_id), "virtio",
                         do_virtio_entry, mod);
+       else if (sym_is(symname, "__mod_i2c_device_table"))
+               do_table(symval, sym->st_size,
+                        sizeof(struct i2c_device_id), "i2c",
+                        do_i2c_entry, mod);
        free(zeros);
 }
 
index 9e8b025250144ce739e80583a095b3059d89110c..7ef1107a72875412e3cdc52f48fe609f7dfbc764 100644 (file)
@@ -18,3 +18,4 @@ obj-$(CONFIG_SECURITY_SELINUX)                += selinux/built-in.o
 obj-$(CONFIG_SECURITY_SMACK)           += commoncap.o smack/built-in.o
 obj-$(CONFIG_SECURITY_CAPABILITIES)    += commoncap.o capability.o
 obj-$(CONFIG_SECURITY_ROOTPLUG)                += commoncap.o root_plug.o
+obj-$(CONFIG_CGROUP_DEVICE)            += device_cgroup.o
index e8c3f5e467055ce93275ac1c901fda861674e402..5edabc7542ae00c46e568456285f9bf5f369f2e6 100644 (file)
@@ -383,8 +383,8 @@ int cap_bprm_secureexec (struct linux_binprm *bprm)
                current->egid != current->gid);
 }
 
-int cap_inode_setxattr(struct dentry *dentry, char *name, void *value,
-                      size_t size, int flags)
+int cap_inode_setxattr(struct dentry *dentry, const char *name,
+                      const void *value, size_t size, int flags)
 {
        if (!strcmp(name, XATTR_NAME_CAPS)) {
                if (!capable(CAP_SETFCAP))
@@ -397,7 +397,7 @@ int cap_inode_setxattr(struct dentry *dentry, char *name, void *value,
        return 0;
 }
 
-int cap_inode_removexattr(struct dentry *dentry, char *name)
+int cap_inode_removexattr(struct dentry *dentry, const char *name)
 {
        if (!strcmp(name, XATTR_NAME_CAPS)) {
                if (!capable(CAP_SETFCAP))
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
new file mode 100644 (file)
index 0000000..4ea5836
--- /dev/null
@@ -0,0 +1,575 @@
+/*
+ * dev_cgroup.c - device cgroup subsystem
+ *
+ * Copyright 2007 IBM Corp
+ */
+
+#include <linux/device_cgroup.h>
+#include <linux/cgroup.h>
+#include <linux/ctype.h>
+#include <linux/list.h>
+#include <linux/uaccess.h>
+#include <linux/seq_file.h>
+
+#define ACC_MKNOD 1
+#define ACC_READ  2
+#define ACC_WRITE 4
+#define ACC_MASK (ACC_MKNOD | ACC_READ | ACC_WRITE)
+
+#define DEV_BLOCK 1
+#define DEV_CHAR  2
+#define DEV_ALL   4  /* this represents all devices */
+
+/*
+ * whitelist locking rules:
+ * cgroup_lock() cannot be taken under dev_cgroup->lock.
+ * dev_cgroup->lock can be taken with or without cgroup_lock().
+ *
+ * modifications always require cgroup_lock
+ * modifications to a list which is visible require the
+ *   dev_cgroup->lock *and* cgroup_lock()
+ * walking the list requires dev_cgroup->lock or cgroup_lock().
+ *
+ * reasoning: dev_whitelist_copy() needs to kmalloc, so needs
+ *   a mutex, which the cgroup_lock() is.  Since modifying
+ *   a visible list requires both locks, either lock can be
+ *   taken for walking the list.
+ */
+
+struct dev_whitelist_item {
+       u32 major, minor;
+       short type;
+       short access;
+       struct list_head list;
+};
+
+struct dev_cgroup {
+       struct cgroup_subsys_state css;
+       struct list_head whitelist;
+       spinlock_t lock;
+};
+
+static inline struct dev_cgroup *cgroup_to_devcgroup(struct cgroup *cgroup)
+{
+       return container_of(cgroup_subsys_state(cgroup, devices_subsys_id),
+                           struct dev_cgroup, css);
+}
+
+struct cgroup_subsys devices_subsys;
+
+static int devcgroup_can_attach(struct cgroup_subsys *ss,
+               struct cgroup *new_cgroup, struct task_struct *task)
+{
+       if (current != task && !capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+
+       return 0;
+}
+
+/*
+ * called under cgroup_lock()
+ */
+static int dev_whitelist_copy(struct list_head *dest, struct list_head *orig)
+{
+       struct dev_whitelist_item *wh, *tmp, *new;
+
+       list_for_each_entry(wh, orig, list) {
+               new = kmalloc(sizeof(*wh), GFP_KERNEL);
+               if (!new)
+                       goto free_and_exit;
+               new->major = wh->major;
+               new->minor = wh->minor;
+               new->type = wh->type;
+               new->access = wh->access;
+               list_add_tail(&new->list, dest);
+       }
+
+       return 0;
+
+free_and_exit:
+       list_for_each_entry_safe(wh, tmp, dest, list) {
+               list_del(&wh->list);
+               kfree(wh);
+       }
+       return -ENOMEM;
+}
+
+/* Stupid prototype - don't bother combining existing entries */
+/*
+ * called under cgroup_lock()
+ * since the list is visible to other tasks, we need the spinlock also
+ */
+static int dev_whitelist_add(struct dev_cgroup *dev_cgroup,
+                       struct dev_whitelist_item *wh)
+{
+       struct dev_whitelist_item *whcopy;
+
+       whcopy = kmalloc(sizeof(*whcopy), GFP_KERNEL);
+       if (!whcopy)
+               return -ENOMEM;
+
+       memcpy(whcopy, wh, sizeof(*whcopy));
+       spin_lock(&dev_cgroup->lock);
+       list_add_tail(&whcopy->list, &dev_cgroup->whitelist);
+       spin_unlock(&dev_cgroup->lock);
+       return 0;
+}
+
+/*
+ * called under cgroup_lock()
+ * since the list is visible to other tasks, we need the spinlock also
+ */
+static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup,
+                       struct dev_whitelist_item *wh)
+{
+       struct dev_whitelist_item *walk, *tmp;
+
+       spin_lock(&dev_cgroup->lock);
+       list_for_each_entry_safe(walk, tmp, &dev_cgroup->whitelist, list) {
+               if (walk->type == DEV_ALL)
+                       goto remove;
+               if (walk->type != wh->type)
+                       continue;
+               if (walk->major != ~0 && walk->major != wh->major)
+                       continue;
+               if (walk->minor != ~0 && walk->minor != wh->minor)
+                       continue;
+
+remove:
+               walk->access &= ~wh->access;
+               if (!walk->access) {
+                       list_del(&walk->list);
+                       kfree(walk);
+               }
+       }
+       spin_unlock(&dev_cgroup->lock);
+}
+
+/*
+ * called from kernel/cgroup.c with cgroup_lock() held.
+ */
+static struct cgroup_subsys_state *devcgroup_create(struct cgroup_subsys *ss,
+                                               struct cgroup *cgroup)
+{
+       struct dev_cgroup *dev_cgroup, *parent_dev_cgroup;
+       struct cgroup *parent_cgroup;
+       int ret;
+
+       dev_cgroup = kzalloc(sizeof(*dev_cgroup), GFP_KERNEL);
+       if (!dev_cgroup)
+               return ERR_PTR(-ENOMEM);
+       INIT_LIST_HEAD(&dev_cgroup->whitelist);
+       parent_cgroup = cgroup->parent;
+
+       if (parent_cgroup == NULL) {
+               struct dev_whitelist_item *wh;
+               wh = kmalloc(sizeof(*wh), GFP_KERNEL);
+               if (!wh) {
+                       kfree(dev_cgroup);
+                       return ERR_PTR(-ENOMEM);
+               }
+               wh->minor = wh->major = ~0;
+               wh->type = DEV_ALL;
+               wh->access = ACC_MKNOD | ACC_READ | ACC_WRITE;
+               list_add(&wh->list, &dev_cgroup->whitelist);
+       } else {
+               parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup);
+               ret = dev_whitelist_copy(&dev_cgroup->whitelist,
+                               &parent_dev_cgroup->whitelist);
+               if (ret) {
+                       kfree(dev_cgroup);
+                       return ERR_PTR(ret);
+               }
+       }
+
+       spin_lock_init(&dev_cgroup->lock);
+       return &dev_cgroup->css;
+}
+
+static void devcgroup_destroy(struct cgroup_subsys *ss,
+                       struct cgroup *cgroup)
+{
+       struct dev_cgroup *dev_cgroup;
+       struct dev_whitelist_item *wh, *tmp;
+
+       dev_cgroup = cgroup_to_devcgroup(cgroup);
+       list_for_each_entry_safe(wh, tmp, &dev_cgroup->whitelist, list) {
+               list_del(&wh->list);
+               kfree(wh);
+       }
+       kfree(dev_cgroup);
+}
+
+#define DEVCG_ALLOW 1
+#define DEVCG_DENY 2
+#define DEVCG_LIST 3
+
+#define MAJMINLEN 10
+#define ACCLEN 4
+
+static void set_access(char *acc, short access)
+{
+       int idx = 0;
+       memset(acc, 0, ACCLEN);
+       if (access & ACC_READ)
+               acc[idx++] = 'r';
+       if (access & ACC_WRITE)
+               acc[idx++] = 'w';
+       if (access & ACC_MKNOD)
+               acc[idx++] = 'm';
+}
+
+static char type_to_char(short type)
+{
+       if (type == DEV_ALL)
+               return 'a';
+       if (type == DEV_CHAR)
+               return 'c';
+       if (type == DEV_BLOCK)
+               return 'b';
+       return 'X';
+}
+
+static void set_majmin(char *str, unsigned m)
+{
+       memset(str, 0, MAJMINLEN);
+       if (m == ~0)
+               sprintf(str, "*");
+       else
+               snprintf(str, MAJMINLEN, "%d", m);
+}
+
+static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
+                               struct seq_file *m)
+{
+       struct dev_cgroup *devcgroup = cgroup_to_devcgroup(cgroup);
+       struct dev_whitelist_item *wh;
+       char maj[MAJMINLEN], min[MAJMINLEN], acc[ACCLEN];
+
+       spin_lock(&devcgroup->lock);
+       list_for_each_entry(wh, &devcgroup->whitelist, list) {
+               set_access(acc, wh->access);
+               set_majmin(maj, wh->major);
+               set_majmin(min, wh->minor);
+               seq_printf(m, "%c %s:%s %s\n", type_to_char(wh->type),
+                          maj, min, acc);
+       }
+       spin_unlock(&devcgroup->lock);
+
+       return 0;
+}
+
+/*
+ * may_access_whitelist:
+ * does the access granted to dev_cgroup c contain the access
+ * requested in whitelist item refwh.
+ * return 1 if yes, 0 if no.
+ * call with c->lock held
+ */
+static int may_access_whitelist(struct dev_cgroup *c,
+                                      struct dev_whitelist_item *refwh)
+{
+       struct dev_whitelist_item *whitem;
+
+       list_for_each_entry(whitem, &c->whitelist, list) {
+               if (whitem->type & DEV_ALL)
+                       return 1;
+               if ((refwh->type & DEV_BLOCK) && !(whitem->type & DEV_BLOCK))
+                       continue;
+               if ((refwh->type & DEV_CHAR) && !(whitem->type & DEV_CHAR))
+                       continue;
+               if (whitem->major != ~0 && whitem->major != refwh->major)
+                       continue;
+               if (whitem->minor != ~0 && whitem->minor != refwh->minor)
+                       continue;
+               if (refwh->access & (~(whitem->access | ACC_MASK)))
+                       continue;
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * parent_has_perm:
+ * when adding a new allow rule to a device whitelist, the rule
+ * must be allowed in the parent device
+ */
+static int parent_has_perm(struct cgroup *childcg,
+                                 struct dev_whitelist_item *wh)
+{
+       struct cgroup *pcg = childcg->parent;
+       struct dev_cgroup *parent;
+       int ret;
+
+       if (!pcg)
+               return 1;
+       parent = cgroup_to_devcgroup(pcg);
+       spin_lock(&parent->lock);
+       ret = may_access_whitelist(parent, wh);
+       spin_unlock(&parent->lock);
+       return ret;
+}
+
+/*
+ * Modify the whitelist using allow/deny rules.
+ * CAP_SYS_ADMIN is needed for this.  It's at least separate from CAP_MKNOD
+ * so we can give a container CAP_MKNOD to let it create devices but not
+ * modify the whitelist.
+ * It seems likely we'll want to add a CAP_CONTAINER capability to allow
+ * us to also grant CAP_SYS_ADMIN to containers without giving away the
+ * device whitelist controls, but for now we'll stick with CAP_SYS_ADMIN
+ *
+ * Taking rules away is always allowed (given CAP_SYS_ADMIN).  Granting
+ * new access is only allowed if you're in the top-level cgroup, or your
+ * parent cgroup has the access you're asking for.
+ */
+static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft,
+                               struct file *file, const char __user *userbuf,
+                               size_t nbytes, loff_t *ppos)
+{
+       struct cgroup *cur_cgroup;
+       struct dev_cgroup *devcgroup, *cur_devcgroup;
+       int filetype = cft->private;
+       char *buffer, *b;
+       int retval = 0, count;
+       struct dev_whitelist_item wh;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       devcgroup = cgroup_to_devcgroup(cgroup);
+       cur_cgroup = task_cgroup(current, devices_subsys.subsys_id);
+       cur_devcgroup = cgroup_to_devcgroup(cur_cgroup);
+
+       buffer = kmalloc(nbytes+1, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
+
+       if (copy_from_user(buffer, userbuf, nbytes)) {
+               retval = -EFAULT;
+               goto out1;
+       }
+       buffer[nbytes] = 0;     /* nul-terminate */
+
+       cgroup_lock();
+       if (cgroup_is_removed(cgroup)) {
+               retval = -ENODEV;
+               goto out2;
+       }
+
+       memset(&wh, 0, sizeof(wh));
+       b = buffer;
+
+       switch (*b) {
+       case 'a':
+               wh.type = DEV_ALL;
+               wh.access = ACC_MASK;
+               goto handle;
+       case 'b':
+               wh.type = DEV_BLOCK;
+               break;
+       case 'c':
+               wh.type = DEV_CHAR;
+               break;
+       default:
+               retval = -EINVAL;
+               goto out2;
+       }
+       b++;
+       if (!isspace(*b)) {
+               retval = -EINVAL;
+               goto out2;
+       }
+       b++;
+       if (*b == '*') {
+               wh.major = ~0;
+               b++;
+       } else if (isdigit(*b)) {
+               wh.major = 0;
+               while (isdigit(*b)) {
+                       wh.major = wh.major*10+(*b-'0');
+                       b++;
+               }
+       } else {
+               retval = -EINVAL;
+               goto out2;
+       }
+       if (*b != ':') {
+               retval = -EINVAL;
+               goto out2;
+       }
+       b++;
+
+       /* read minor */
+       if (*b == '*') {
+               wh.minor = ~0;
+               b++;
+       } else if (isdigit(*b)) {
+               wh.minor = 0;
+               while (isdigit(*b)) {
+                       wh.minor = wh.minor*10+(*b-'0');
+                       b++;
+               }
+       } else {
+               retval = -EINVAL;
+               goto out2;
+       }
+       if (!isspace(*b)) {
+               retval = -EINVAL;
+               goto out2;
+       }
+       for (b++, count = 0; count < 3; count++, b++) {
+               switch (*b) {
+               case 'r':
+                       wh.access |= ACC_READ;
+                       break;
+               case 'w':
+                       wh.access |= ACC_WRITE;
+                       break;
+               case 'm':
+                       wh.access |= ACC_MKNOD;
+                       break;
+               case '\n':
+               case '\0':
+                       count = 3;
+                       break;
+               default:
+                       retval = -EINVAL;
+                       goto out2;
+               }
+       }
+
+handle:
+       retval = 0;
+       switch (filetype) {
+       case DEVCG_ALLOW:
+               if (!parent_has_perm(cgroup, &wh))
+                       retval = -EPERM;
+               else
+                       retval = dev_whitelist_add(devcgroup, &wh);
+               break;
+       case DEVCG_DENY:
+               dev_whitelist_rm(devcgroup, &wh);
+               break;
+       default:
+               retval = -EINVAL;
+               goto out2;
+       }
+
+       if (retval == 0)
+               retval = nbytes;
+
+out2:
+       cgroup_unlock();
+out1:
+       kfree(buffer);
+       return retval;
+}
+
+static struct cftype dev_cgroup_files[] = {
+       {
+               .name = "allow",
+               .write  = devcgroup_access_write,
+               .private = DEVCG_ALLOW,
+       },
+       {
+               .name = "deny",
+               .write = devcgroup_access_write,
+               .private = DEVCG_DENY,
+       },
+       {
+               .name = "list",
+               .read_seq_string = devcgroup_seq_read,
+               .private = DEVCG_LIST,
+       },
+};
+
+static int devcgroup_populate(struct cgroup_subsys *ss,
+                               struct cgroup *cgroup)
+{
+       return cgroup_add_files(cgroup, ss, dev_cgroup_files,
+                                       ARRAY_SIZE(dev_cgroup_files));
+}
+
+struct cgroup_subsys devices_subsys = {
+       .name = "devices",
+       .can_attach = devcgroup_can_attach,
+       .create = devcgroup_create,
+       .destroy  = devcgroup_destroy,
+       .populate = devcgroup_populate,
+       .subsys_id = devices_subsys_id,
+};
+
+int devcgroup_inode_permission(struct inode *inode, int mask)
+{
+       struct cgroup *cgroup;
+       struct dev_cgroup *dev_cgroup;
+       struct dev_whitelist_item *wh;
+
+       dev_t device = inode->i_rdev;
+       if (!device)
+               return 0;
+       if (!S_ISBLK(inode->i_mode) && !S_ISCHR(inode->i_mode))
+               return 0;
+       cgroup = task_cgroup(current, devices_subsys.subsys_id);
+       dev_cgroup = cgroup_to_devcgroup(cgroup);
+       if (!dev_cgroup)
+               return 0;
+
+       spin_lock(&dev_cgroup->lock);
+       list_for_each_entry(wh, &dev_cgroup->whitelist, list) {
+               if (wh->type & DEV_ALL)
+                       goto acc_check;
+               if ((wh->type & DEV_BLOCK) && !S_ISBLK(inode->i_mode))
+                       continue;
+               if ((wh->type & DEV_CHAR) && !S_ISCHR(inode->i_mode))
+                       continue;
+               if (wh->major != ~0 && wh->major != imajor(inode))
+                       continue;
+               if (wh->minor != ~0 && wh->minor != iminor(inode))
+                       continue;
+acc_check:
+               if ((mask & MAY_WRITE) && !(wh->access & ACC_WRITE))
+                       continue;
+               if ((mask & MAY_READ) && !(wh->access & ACC_READ))
+                       continue;
+               spin_unlock(&dev_cgroup->lock);
+               return 0;
+       }
+       spin_unlock(&dev_cgroup->lock);
+
+       return -EPERM;
+}
+
+int devcgroup_inode_mknod(int mode, dev_t dev)
+{
+       struct cgroup *cgroup;
+       struct dev_cgroup *dev_cgroup;
+       struct dev_whitelist_item *wh;
+
+       cgroup = task_cgroup(current, devices_subsys.subsys_id);
+       dev_cgroup = cgroup_to_devcgroup(cgroup);
+       if (!dev_cgroup)
+               return 0;
+
+       spin_lock(&dev_cgroup->lock);
+       list_for_each_entry(wh, &dev_cgroup->whitelist, list) {
+               if (wh->type & DEV_ALL)
+                       goto acc_check;
+               if ((wh->type & DEV_BLOCK) && !S_ISBLK(mode))
+                       continue;
+               if ((wh->type & DEV_CHAR) && !S_ISCHR(mode))
+                       continue;
+               if (wh->major != ~0 && wh->major != MAJOR(dev))
+                       continue;
+               if (wh->minor != ~0 && wh->minor != MINOR(dev))
+                       continue;
+acc_check:
+               if (!(wh->access & ACC_MKNOD))
+                       continue;
+               spin_unlock(&dev_cgroup->lock);
+               return 0;
+       }
+       spin_unlock(&dev_cgroup->lock);
+       return -EPERM;
+}
index 58d4dd1af5c7054f76d1d26e7b407eaaed12a25a..f50c6c3c32c9542eb796ba5c162b2bb08ea52ea9 100644 (file)
@@ -365,8 +365,8 @@ static void dummy_inode_delete (struct inode *ino)
        return;
 }
 
-static int dummy_inode_setxattr (struct dentry *dentry, char *name, void *value,
-                               size_t size, int flags)
+static int dummy_inode_setxattr (struct dentry *dentry, const char *name,
+                                const void *value, size_t size, int flags)
 {
        if (!strncmp(name, XATTR_SECURITY_PREFIX,
                     sizeof(XATTR_SECURITY_PREFIX) - 1) &&
@@ -375,12 +375,13 @@ static int dummy_inode_setxattr (struct dentry *dentry, char *name, void *value,
        return 0;
 }
 
-static void dummy_inode_post_setxattr (struct dentry *dentry, char *name, void *value,
-                                      size_t size, int flags)
+static void dummy_inode_post_setxattr (struct dentry *dentry, const char *name,
+                                      const void *value, size_t size,
+                                      int flags)
 {
 }
 
-static int dummy_inode_getxattr (struct dentry *dentry, char *name)
+static int dummy_inode_getxattr (struct dentry *dentry, const char *name)
 {
        return 0;
 }
@@ -390,7 +391,7 @@ static int dummy_inode_listxattr (struct dentry *dentry)
        return 0;
 }
 
-static int dummy_inode_removexattr (struct dentry *dentry, char *name)
+static int dummy_inode_removexattr (struct dentry *dentry, const char *name)
 {
        if (!strncmp(name, XATTR_SECURITY_PREFIX,
                     sizeof(XATTR_SECURITY_PREFIX) - 1) &&
@@ -967,7 +968,7 @@ static int dummy_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
        return -EOPNOTSUPP;
 }
 
-static int dummy_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
+static int dummy_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
 {
        return -EOPNOTSUPP;
 }
@@ -993,6 +994,13 @@ static inline int dummy_key_permission(key_ref_t key_ref,
 {
        return 0;
 }
+
+static int dummy_key_getsecurity(struct key *key, char **_buffer)
+{
+       *_buffer = NULL;
+       return 0;
+}
+
 #endif /* CONFIG_KEYS */
 
 #ifdef CONFIG_AUDIT
@@ -1209,6 +1217,7 @@ void security_fixup_ops (struct security_operations *ops)
        set_to_dummy_if_null(ops, key_alloc);
        set_to_dummy_if_null(ops, key_free);
        set_to_dummy_if_null(ops, key_permission);
+       set_to_dummy_if_null(ops, key_getsecurity);
 #endif /* CONFIG_KEYS */
 #ifdef CONFIG_AUDIT
        set_to_dummy_if_null(ops, audit_rule_init);
index 5145adfb6a05cabec8864b81ee7c5f692dbf03cd..747a464943aff0ada556e903fa6750fc7b670b60 100644 (file)
@@ -14,3 +14,4 @@ obj-y := \
 
 obj-$(CONFIG_KEYS_COMPAT) += compat.o
 obj-$(CONFIG_PROC_FS) += proc.o
+obj-$(CONFIG_SYSCTL) += sysctl.o
index e10ec995f2751101d39a7dfbd145cd8ce52cc6ee..c766c68a63bc2078c62bf256730e05e14b36268b 100644 (file)
@@ -79,6 +79,9 @@ asmlinkage long compat_sys_keyctl(u32 option,
        case KEYCTL_ASSUME_AUTHORITY:
                return keyctl_assume_authority(arg2);
 
+       case KEYCTL_GET_SECURITY:
+               return keyctl_get_security(arg2, compat_ptr(arg3), arg4);
+
        default:
                return -EOPNOTSUPP;
        }
index 7d894ef70370bcb2c4906447c22965ba829a1e2a..8c05587f5018b49147bf44ed5f4ad846a173573b 100644 (file)
@@ -57,10 +57,6 @@ struct key_user {
        int                     qnbytes;        /* number of bytes allocated to this user */
 };
 
-#define KEYQUOTA_MAX_KEYS      100
-#define KEYQUOTA_MAX_BYTES     10000
-#define KEYQUOTA_LINK_BYTES    4               /* a link in a keyring is worth 4 bytes */
-
 extern struct rb_root  key_user_tree;
 extern spinlock_t      key_user_lock;
 extern struct key_user root_key_user;
@@ -68,6 +64,16 @@ extern struct key_user       root_key_user;
 extern struct key_user *key_user_lookup(uid_t uid);
 extern void key_user_put(struct key_user *user);
 
+/*
+ * key quota limits
+ * - root has its own separate limits to everyone else
+ */
+extern unsigned key_quota_root_maxkeys;
+extern unsigned key_quota_root_maxbytes;
+extern unsigned key_quota_maxkeys;
+extern unsigned key_quota_maxbytes;
+
+#define KEYQUOTA_LINK_BYTES    4               /* a link in a keyring is worth 4 bytes */
 
 
 extern struct rb_root key_serial_tree;
@@ -77,8 +83,6 @@ extern struct mutex key_construction_mutex;
 extern wait_queue_head_t request_key_conswq;
 
 
-extern void keyring_publish_name(struct key *keyring);
-
 extern int __key_link(struct key *keyring, struct key *key);
 
 extern key_ref_t __keyring_search_one(key_ref_t keyring_ref,
@@ -102,14 +106,15 @@ extern key_ref_t search_process_keyrings(struct key_type *type,
                                         key_match_func_t match,
                                         struct task_struct *tsk);
 
-extern struct key *find_keyring_by_name(const char *name, key_serial_t bound);
+extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check);
 
 extern int install_thread_keyring(struct task_struct *tsk);
 extern int install_process_keyring(struct task_struct *tsk);
 
 extern struct key *request_key_and_link(struct key_type *type,
                                        const char *description,
-                                       const char *callout_info,
+                                       const void *callout_info,
+                                       size_t callout_len,
                                        void *aux,
                                        struct key *dest_keyring,
                                        unsigned long flags);
@@ -120,13 +125,15 @@ extern struct key *request_key_and_link(struct key_type *type,
 struct request_key_auth {
        struct key              *target_key;
        struct task_struct      *context;
-       char                    *callout_info;
+       void                    *callout_info;
+       size_t                  callout_len;
        pid_t                   pid;
 };
 
 extern struct key_type key_type_request_key_auth;
 extern struct key *request_key_auth_new(struct key *target,
-                                       const char *callout_info);
+                                       const void *callout_info,
+                                       size_t callout_len);
 
 extern struct key *key_get_instantiation_authkey(key_serial_t target_id);
 
@@ -152,7 +159,8 @@ extern long keyctl_negate_key(key_serial_t, unsigned, key_serial_t);
 extern long keyctl_set_reqkey_keyring(int);
 extern long keyctl_set_timeout(key_serial_t, unsigned);
 extern long keyctl_assume_authority(key_serial_t);
-
+extern long keyctl_get_security(key_serial_t keyid, char __user *buffer,
+                               size_t buflen);
 
 /*
  * debugging key validation
index 654d23baf3525ceee6134f75039a4d450fc1edd9..14948cf83ef6acc6ea19811465201ff5ae8660f0 100644 (file)
@@ -1,6 +1,6 @@
 /* Basic authentication token and access key management
  *
- * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-2008 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -27,6 +27,11 @@ DEFINE_SPINLOCK(key_serial_lock);
 struct rb_root key_user_tree; /* tree of quota records indexed by UID */
 DEFINE_SPINLOCK(key_user_lock);
 
+unsigned int key_quota_root_maxkeys = 200;     /* root's key count quota */
+unsigned int key_quota_root_maxbytes = 20000;  /* root's key space quota */
+unsigned int key_quota_maxkeys = 200;          /* general key count quota */
+unsigned int key_quota_maxbytes = 20000;       /* general key space quota */
+
 static LIST_HEAD(key_types_list);
 static DECLARE_RWSEM(key_types_sem);
 
@@ -137,36 +142,6 @@ void key_user_put(struct key_user *user)
 
 } /* end key_user_put() */
 
-/*****************************************************************************/
-/*
- * insert a key with a fixed serial number
- */
-static void __init __key_insert_serial(struct key *key)
-{
-       struct rb_node *parent, **p;
-       struct key *xkey;
-
-       parent = NULL;
-       p = &key_serial_tree.rb_node;
-
-       while (*p) {
-               parent = *p;
-               xkey = rb_entry(parent, struct key, serial_node);
-
-               if (key->serial < xkey->serial)
-                       p = &(*p)->rb_left;
-               else if (key->serial > xkey->serial)
-                       p = &(*p)->rb_right;
-               else
-                       BUG();
-       }
-
-       /* we've found a suitable hole - arrange for this key to occupy it */
-       rb_link_node(&key->serial_node, parent, p);
-       rb_insert_color(&key->serial_node, &key_serial_tree);
-
-} /* end __key_insert_serial() */
-
 /*****************************************************************************/
 /*
  * assign a key the next unique serial number
@@ -266,11 +241,16 @@ struct key *key_alloc(struct key_type *type, const char *desc,
        /* check that the user's quota permits allocation of another key and
         * its description */
        if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) {
+               unsigned maxkeys = (uid == 0) ?
+                       key_quota_root_maxkeys : key_quota_maxkeys;
+               unsigned maxbytes = (uid == 0) ?
+                       key_quota_root_maxbytes : key_quota_maxbytes;
+
                spin_lock(&user->lock);
                if (!(flags & KEY_ALLOC_QUOTA_OVERRUN)) {
-                       if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS ||
-                           user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES
-                           )
+                       if (user->qnkeys + 1 >= maxkeys ||
+                           user->qnbytes + quotalen >= maxbytes ||
+                           user->qnbytes + quotalen < user->qnbytes)
                                goto no_quota;
                }
 
@@ -375,11 +355,14 @@ int key_payload_reserve(struct key *key, size_t datalen)
 
        /* contemplate the quota adjustment */
        if (delta != 0 && test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
+               unsigned maxbytes = (key->user->uid == 0) ?
+                       key_quota_root_maxbytes : key_quota_maxbytes;
+
                spin_lock(&key->user->lock);
 
                if (delta > 0 &&
-                   key->user->qnbytes + delta > KEYQUOTA_MAX_BYTES
-                   ) {
+                   (key->user->qnbytes + delta >= maxbytes ||
+                    key->user->qnbytes + delta < key->user->qnbytes)) {
                        ret = -EDQUOT;
                }
                else {
@@ -757,11 +740,11 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
                               const char *description,
                               const void *payload,
                               size_t plen,
+                              key_perm_t perm,
                               unsigned long flags)
 {
        struct key_type *ktype;
        struct key *keyring, *key = NULL;
-       key_perm_t perm;
        key_ref_t key_ref;
        int ret;
 
@@ -806,15 +789,17 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
                        goto found_matching_key;
        }
 
-       /* decide on the permissions we want */
-       perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
-       perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR;
+       /* if the client doesn't provide, decide on the permissions we want */
+       if (perm == KEY_PERM_UNDEF) {
+               perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
+               perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR;
 
-       if (ktype->read)
-               perm |= KEY_POS_READ | KEY_USR_READ;
+               if (ktype->read)
+                       perm |= KEY_POS_READ | KEY_USR_READ;
 
-       if (ktype == &key_type_keyring || ktype->update)
-               perm |= KEY_USR_WRITE;
+               if (ktype == &key_type_keyring || ktype->update)
+                       perm |= KEY_USR_WRITE;
+       }
 
        /* allocate a new key */
        key = key_alloc(ktype, description, current->fsuid, current->fsgid,
@@ -1018,17 +1003,4 @@ void __init key_init(void)
        rb_insert_color(&root_key_user.node,
                        &key_user_tree);
 
-       /* record root's user standard keyrings */
-       key_check(&root_user_keyring);
-       key_check(&root_session_keyring);
-
-       __key_insert_serial(&root_user_keyring);
-       __key_insert_serial(&root_session_keyring);
-
-       keyring_publish_name(&root_user_keyring);
-       keyring_publish_name(&root_session_keyring);
-
-       /* link the two root keyrings together */
-       key_link(&root_session_keyring, &root_user_keyring);
-
 } /* end key_init() */
index d9ca15c109ccfaa167cafc8c39dec87f2a3e305d..acc9c89e40a8de6937cba2971c8805e09a4d0f6f 100644 (file)
@@ -19,6 +19,8 @@
 #include <linux/capability.h>
 #include <linux/string.h>
 #include <linux/err.h>
+#include <linux/vmalloc.h>
+#include <linux/security.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
@@ -62,9 +64,10 @@ asmlinkage long sys_add_key(const char __user *_type,
        char type[32], *description;
        void *payload;
        long ret;
+       bool vm;
 
        ret = -EINVAL;
-       if (plen > 32767)
+       if (plen > 1024 * 1024 - 1)
                goto error;
 
        /* draw all the data into kernel space */
@@ -81,11 +84,18 @@ asmlinkage long sys_add_key(const char __user *_type,
        /* pull the payload in if one was supplied */
        payload = NULL;
 
+       vm = false;
        if (_payload) {
                ret = -ENOMEM;
                payload = kmalloc(plen, GFP_KERNEL);
-               if (!payload)
-                       goto error2;
+               if (!payload) {
+                       if (plen <= PAGE_SIZE)
+                               goto error2;
+                       vm = true;
+                       payload = vmalloc(plen);
+                       if (!payload)
+                               goto error2;
+               }
 
                ret = -EFAULT;
                if (copy_from_user(payload, _payload, plen) != 0)
@@ -102,7 +112,8 @@ asmlinkage long sys_add_key(const char __user *_type,
        /* create or update the requested key and add it to the target
         * keyring */
        key_ref = key_create_or_update(keyring_ref, type, description,
-                                      payload, plen, KEY_ALLOC_IN_QUOTA);
+                                      payload, plen, KEY_PERM_UNDEF,
+                                      KEY_ALLOC_IN_QUOTA);
        if (!IS_ERR(key_ref)) {
                ret = key_ref_to_ptr(key_ref)->serial;
                key_ref_put(key_ref);
@@ -113,7 +124,10 @@ asmlinkage long sys_add_key(const char __user *_type,
 
        key_ref_put(keyring_ref);
  error3:
-       kfree(payload);
+       if (!vm)
+               kfree(payload);
+       else
+               vfree(payload);
  error2:
        kfree(description);
  error:
@@ -140,6 +154,7 @@ asmlinkage long sys_request_key(const char __user *_type,
        struct key_type *ktype;
        struct key *key;
        key_ref_t dest_ref;
+       size_t callout_len;
        char type[32], *description, *callout_info;
        long ret;
 
@@ -157,12 +172,14 @@ asmlinkage long sys_request_key(const char __user *_type,
 
        /* pull the callout info into kernel space */
        callout_info = NULL;
+       callout_len = 0;
        if (_callout_info) {
                callout_info = strndup_user(_callout_info, PAGE_SIZE);
                if (IS_ERR(callout_info)) {
                        ret = PTR_ERR(callout_info);
                        goto error2;
                }
+               callout_len = strlen(callout_info);
        }
 
        /* get the destination keyring if specified */
@@ -183,8 +200,8 @@ asmlinkage long sys_request_key(const char __user *_type,
        }
 
        /* do the search */
-       key = request_key_and_link(ktype, description, callout_info, NULL,
-                                  key_ref_to_ptr(dest_ref),
+       key = request_key_and_link(ktype, description, callout_info,
+                                  callout_len, NULL, key_ref_to_ptr(dest_ref),
                                   KEY_ALLOC_IN_QUOTA);
        if (IS_ERR(key)) {
                ret = PTR_ERR(key);
@@ -714,10 +731,16 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
 
                /* transfer the quota burden to the new user */
                if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
+                       unsigned maxkeys = (uid == 0) ?
+                               key_quota_root_maxkeys : key_quota_maxkeys;
+                       unsigned maxbytes = (uid == 0) ?
+                               key_quota_root_maxbytes : key_quota_maxbytes;
+
                        spin_lock(&newowner->lock);
-                       if (newowner->qnkeys + 1 >= KEYQUOTA_MAX_KEYS ||
-                           newowner->qnbytes + key->quotalen >=
-                           KEYQUOTA_MAX_BYTES)
+                       if (newowner->qnkeys + 1 >= maxkeys ||
+                           newowner->qnbytes + key->quotalen >= maxbytes ||
+                           newowner->qnbytes + key->quotalen <
+                           newowner->qnbytes)
                                goto quota_overrun;
 
                        newowner->qnkeys++;
@@ -821,9 +844,10 @@ long keyctl_instantiate_key(key_serial_t id,
        key_ref_t keyring_ref;
        void *payload;
        long ret;
+       bool vm = false;
 
        ret = -EINVAL;
-       if (plen > 32767)
+       if (plen > 1024 * 1024 - 1)
                goto error;
 
        /* the appropriate instantiation authorisation key must have been
@@ -843,8 +867,14 @@ long keyctl_instantiate_key(key_serial_t id,
        if (_payload) {
                ret = -ENOMEM;
                payload = kmalloc(plen, GFP_KERNEL);
-               if (!payload)
-                       goto error;
+               if (!payload) {
+                       if (plen <= PAGE_SIZE)
+                               goto error;
+                       vm = true;
+                       payload = vmalloc(plen);
+                       if (!payload)
+                               goto error;
+               }
 
                ret = -EFAULT;
                if (copy_from_user(payload, _payload, plen) != 0)
@@ -877,7 +907,10 @@ long keyctl_instantiate_key(key_serial_t id,
        }
 
 error2:
-       kfree(payload);
+       if (!vm)
+               kfree(payload);
+       else
+               vfree(payload);
 error:
        return ret;
 
@@ -1055,6 +1088,66 @@ error:
 
 } /* end keyctl_assume_authority() */
 
+/*
+ * get the security label of a key
+ * - the key must grant us view permission
+ * - if there's a buffer, we place up to buflen bytes of data into it
+ * - unless there's an error, we return the amount of information available,
+ *   irrespective of how much we may have copied (including the terminal NUL)
+ * - implements keyctl(KEYCTL_GET_SECURITY)
+ */
+long keyctl_get_security(key_serial_t keyid,
+                        char __user *buffer,
+                        size_t buflen)
+{
+       struct key *key, *instkey;
+       key_ref_t key_ref;
+       char *context;
+       long ret;
+
+       key_ref = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW);
+       if (IS_ERR(key_ref)) {
+               if (PTR_ERR(key_ref) != -EACCES)
+                       return PTR_ERR(key_ref);
+
+               /* viewing a key under construction is also permitted if we
+                * have the authorisation token handy */
+               instkey = key_get_instantiation_authkey(keyid);
+               if (IS_ERR(instkey))
+                       return PTR_ERR(key_ref);
+               key_put(instkey);
+
+               key_ref = lookup_user_key(NULL, keyid, 0, 1, 0);
+               if (IS_ERR(key_ref))
+                       return PTR_ERR(key_ref);
+       }
+
+       key = key_ref_to_ptr(key_ref);
+       ret = security_key_getsecurity(key, &context);
+       if (ret == 0) {
+               /* if no information was returned, give userspace an empty
+                * string */
+               ret = 1;
+               if (buffer && buflen > 0 &&
+                   copy_to_user(buffer, "", 1) != 0)
+                       ret = -EFAULT;
+       } else if (ret > 0) {
+               /* return as much data as there's room for */
+               if (buffer && buflen > 0) {
+                       if (buflen > ret)
+                               buflen = ret;
+
+                       if (copy_to_user(buffer, context, buflen) != 0)
+                               ret = -EFAULT;
+               }
+
+               kfree(context);
+       }
+
+       key_ref_put(key_ref);
+       return ret;
+}
+
 /*****************************************************************************/
 /*
  * the key control system call
@@ -1135,6 +1228,11 @@ asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
        case KEYCTL_ASSUME_AUTHORITY:
                return keyctl_assume_authority((key_serial_t) arg2);
 
+       case KEYCTL_GET_SECURITY:
+               return keyctl_get_security((key_serial_t) arg2,
+                                          (char *) arg3,
+                                          (size_t) arg4);
+
        default:
                return -EOPNOTSUPP;
        }
index 88292e3dee966103fff3f4a9e1cba7b5d22fc5c9..a9ab8affc092d99d1f4d55da9f5c6d10964bb4a1 100644 (file)
@@ -1,6 +1,6 @@
-/* keyring.c: keyring handling
+/* Keyring handling
  *
- * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-2005, 2008 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -79,7 +79,7 @@ static DECLARE_RWSEM(keyring_serialise_link_sem);
  * publish the name of a keyring so that it can be found by name (if it has
  * one)
  */
-void keyring_publish_name(struct key *keyring)
+static void keyring_publish_name(struct key *keyring)
 {
        int bucket;
 
@@ -292,7 +292,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
 
        struct keyring_list *keylist;
        struct timespec now;
-       unsigned long possessed;
+       unsigned long possessed, kflags;
        struct key *keyring, *key;
        key_ref_t key_ref;
        long err;
@@ -319,6 +319,32 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
        err = -EAGAIN;
        sp = 0;
 
+       /* firstly we should check to see if this top-level keyring is what we
+        * are looking for */
+       key_ref = ERR_PTR(-EAGAIN);
+       kflags = keyring->flags;
+       if (keyring->type == type && match(keyring, description)) {
+               key = keyring;
+
+               /* check it isn't negative and hasn't expired or been
+                * revoked */
+               if (kflags & (1 << KEY_FLAG_REVOKED))
+                       goto error_2;
+               if (key->expiry && now.tv_sec >= key->expiry)
+                       goto error_2;
+               key_ref = ERR_PTR(-ENOKEY);
+               if (kflags & (1 << KEY_FLAG_NEGATIVE))
+                       goto error_2;
+               goto found;
+       }
+
+       /* otherwise, the top keyring must not be revoked, expired, or
+        * negatively instantiated if we are to search it */
+       key_ref = ERR_PTR(-EAGAIN);
+       if (kflags & ((1 << KEY_FLAG_REVOKED) | (1 << KEY_FLAG_NEGATIVE)) ||
+           (keyring->expiry && now.tv_sec >= keyring->expiry))
+               goto error_2;
+
        /* start processing a new keyring */
 descend:
        if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
@@ -331,13 +357,14 @@ descend:
        /* iterate through the keys in this keyring first */
        for (kix = 0; kix < keylist->nkeys; kix++) {
                key = keylist->keys[kix];
+               kflags = key->flags;
 
                /* ignore keys not of this type */
                if (key->type != type)
                        continue;
 
                /* skip revoked keys and expired keys */
-               if (test_bit(KEY_FLAG_REVOKED, &key->flags))
+               if (kflags & (1 << KEY_FLAG_REVOKED))
                        continue;
 
                if (key->expiry && now.tv_sec >= key->expiry)
@@ -352,8 +379,8 @@ descend:
                                        context, KEY_SEARCH) < 0)
                        continue;
 
-               /* we set a different error code if we find a negative key */
-               if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
+               /* we set a different error code if we pass a negative key */
+               if (kflags & (1 << KEY_FLAG_NEGATIVE)) {
                        err = -ENOKEY;
                        continue;
                }
@@ -489,10 +516,9 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref,
 /*
  * find a keyring with the specified name
  * - all named keyrings are searched
- * - only find keyrings with search permission for the process
- * - only find keyrings with a serial number greater than the one specified
+ * - normally only finds keyrings with search permission for the current process
  */
-struct key *find_keyring_by_name(const char *name, key_serial_t bound)
+struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
 {
        struct key *keyring;
        int bucket;
@@ -518,15 +544,11 @@ 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),
+                       if (!skip_perm_check &&
+                           key_permission(make_key_ref(keyring, 0),
                                           KEY_SEARCH) < 0)
                                continue;
 
-                       /* found a potential candidate, but we still need to
-                        * check the serial number */
-                       if (keyring->serial <= bound)
-                               continue;
-
                        /* we've got a match */
                        atomic_inc(&keyring->usage);
                        read_unlock(&keyring_name_lock);
index 694126003ed3bcfaacc980e3210540de38cda107..f619170da760688f4d40c856ab2adb1a999fff26 100644 (file)
@@ -70,19 +70,15 @@ static int __init key_proc_init(void)
        struct proc_dir_entry *p;
 
 #ifdef CONFIG_KEYS_DEBUG_PROC_KEYS
-       p = create_proc_entry("keys", 0, NULL);
+       p = proc_create("keys", 0, NULL, &proc_keys_fops);
        if (!p)
                panic("Cannot create /proc/keys\n");
-
-       p->proc_fops = &proc_keys_fops;
 #endif
 
-       p = create_proc_entry("key-users", 0, NULL);
+       p = proc_create("key-users", 0, NULL, &proc_key_users_fops);
        if (!p)
                panic("Cannot create /proc/key-users\n");
 
-       p->proc_fops = &proc_key_users_fops;
-
        return 0;
 
 } /* end key_proc_init() */
@@ -246,6 +242,10 @@ static int proc_key_users_show(struct seq_file *m, void *v)
 {
        struct rb_node *_p = v;
        struct key_user *user = rb_entry(_p, struct key_user, node);
+       unsigned maxkeys = (user->uid == 0) ?
+               key_quota_root_maxkeys : key_quota_maxkeys;
+       unsigned maxbytes = (user->uid == 0) ?
+               key_quota_root_maxbytes : key_quota_maxbytes;
 
        seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n",
                   user->uid,
@@ -253,10 +253,9 @@ static int proc_key_users_show(struct seq_file *m, void *v)
                   atomic_read(&user->nkeys),
                   atomic_read(&user->nikeys),
                   user->qnkeys,
-                  KEYQUOTA_MAX_KEYS,
+                  maxkeys,
                   user->qnbytes,
-                  KEYQUOTA_MAX_BYTES
-                  );
+                  maxbytes);
 
        return 0;
 
index c886a2bb792ae034950ec71aa20af5fd1d4c17ee..5be6d018759abf43d469bc786d04305223464574 100644 (file)
@@ -1,6 +1,6 @@
-/* process_keys.c: management of a process's keyrings
+/* Management of a process's keyrings
  *
- * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-2005, 2008 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -23,6 +23,9 @@
 /* session keyring create vs join semaphore */
 static DEFINE_MUTEX(key_session_mutex);
 
+/* user keyring creation semaphore */
+static DEFINE_MUTEX(key_user_keyring_mutex);
+
 /* the root user's tracking struct */
 struct key_user root_key_user = {
        .usage          = ATOMIC_INIT(3),
@@ -33,78 +36,84 @@ struct key_user root_key_user = {
        .uid            = 0,
 };
 
-/* the root user's UID keyring */
-struct key root_user_keyring = {
-       .usage          = ATOMIC_INIT(1),
-       .serial         = 2,
-       .type           = &key_type_keyring,
-       .user           = &root_key_user,
-       .sem            = __RWSEM_INITIALIZER(root_user_keyring.sem),
-       .perm           = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
-       .flags          = 1 << KEY_FLAG_INSTANTIATED,
-       .description    = "_uid.0",
-#ifdef KEY_DEBUGGING
-       .magic          = KEY_DEBUG_MAGIC,
-#endif
-};
-
-/* the root user's default session keyring */
-struct key root_session_keyring = {
-       .usage          = ATOMIC_INIT(1),
-       .serial         = 1,
-       .type           = &key_type_keyring,
-       .user           = &root_key_user,
-       .sem            = __RWSEM_INITIALIZER(root_session_keyring.sem),
-       .perm           = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
-       .flags          = 1 << KEY_FLAG_INSTANTIATED,
-       .description    = "_uid_ses.0",
-#ifdef KEY_DEBUGGING
-       .magic          = KEY_DEBUG_MAGIC,
-#endif
-};
-
 /*****************************************************************************/
 /*
- * allocate the keyrings to be associated with a UID
+ * install user and user session keyrings for a particular UID
  */
-int alloc_uid_keyring(struct user_struct *user,
-                     struct task_struct *ctx)
+static int install_user_keyrings(struct task_struct *tsk)
 {
+       struct user_struct *user = tsk->user;
        struct key *uid_keyring, *session_keyring;
        char buf[20];
        int ret;
 
-       /* concoct a default session keyring */
-       sprintf(buf, "_uid_ses.%u", user->uid);
+       kenter("%p{%u}", user, user->uid);
 
-       session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx,
-                                       KEY_ALLOC_IN_QUOTA, NULL);
-       if (IS_ERR(session_keyring)) {
-               ret = PTR_ERR(session_keyring);
-               goto error;
+       if (user->uid_keyring) {
+               kleave(" = 0 [exist]");
+               return 0;
        }
 
-       /* and a UID specific keyring, pointed to by the default session
-        * keyring */
-       sprintf(buf, "_uid.%u", user->uid);
+       mutex_lock(&key_user_keyring_mutex);
+       ret = 0;
 
-       uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx,
-                                   KEY_ALLOC_IN_QUOTA, session_keyring);
-       if (IS_ERR(uid_keyring)) {
-               key_put(session_keyring);
-               ret = PTR_ERR(uid_keyring);
-               goto error;
+       if (!user->uid_keyring) {
+               /* get the UID-specific keyring
+                * - there may be one in existence already as it may have been
+                *   pinned by a session, but the user_struct pointing to it
+                *   may have been destroyed by setuid */
+               sprintf(buf, "_uid.%u", user->uid);
+
+               uid_keyring = find_keyring_by_name(buf, true);
+               if (IS_ERR(uid_keyring)) {
+                       uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1,
+                                                   tsk, KEY_ALLOC_IN_QUOTA,
+                                                   NULL);
+                       if (IS_ERR(uid_keyring)) {
+                               ret = PTR_ERR(uid_keyring);
+                               goto error;
+                       }
+               }
+
+               /* get a default session keyring (which might also exist
+                * already) */
+               sprintf(buf, "_uid_ses.%u", user->uid);
+
+               session_keyring = find_keyring_by_name(buf, true);
+               if (IS_ERR(session_keyring)) {
+                       session_keyring =
+                               keyring_alloc(buf, user->uid, (gid_t) -1,
+                                             tsk, KEY_ALLOC_IN_QUOTA, NULL);
+                       if (IS_ERR(session_keyring)) {
+                               ret = PTR_ERR(session_keyring);
+                               goto error_release;
+                       }
+
+                       /* we install a link from the user session keyring to
+                        * the user keyring */
+                       ret = key_link(session_keyring, uid_keyring);
+                       if (ret < 0)
+                               goto error_release_both;
+               }
+
+               /* install the keyrings */
+               user->uid_keyring = uid_keyring;
+               user->session_keyring = session_keyring;
        }
 
-       /* install the keyrings */
-       user->uid_keyring = uid_keyring;
-       user->session_keyring = session_keyring;
-       ret = 0;
+       mutex_unlock(&key_user_keyring_mutex);
+       kleave(" = 0");
+       return 0;
 
+error_release_both:
+       key_put(session_keyring);
+error_release:
+       key_put(uid_keyring);
 error:
+       mutex_unlock(&key_user_keyring_mutex);
+       kleave(" = %d", ret);
        return ret;
-
-} /* end alloc_uid_keyring() */
+}
 
 /*****************************************************************************/
 /*
@@ -481,7 +490,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
                }
        }
        /* or search the user-session keyring */
-       else {
+       else if (context->user->session_keyring) {
                key_ref = keyring_search_aux(
                        make_key_ref(context->user->session_keyring, 1),
                        context, type, description, match);
@@ -614,6 +623,9 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
                if (!context->signal->session_keyring) {
                        /* always install a session keyring upon access if one
                         * doesn't exist yet */
+                       ret = install_user_keyrings(context);
+                       if (ret < 0)
+                               goto error;
                        ret = install_session_keyring(
                                context, context->user->session_keyring);
                        if (ret < 0)
@@ -628,12 +640,24 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
                break;
 
        case KEY_SPEC_USER_KEYRING:
+               if (!context->user->uid_keyring) {
+                       ret = install_user_keyrings(context);
+                       if (ret < 0)
+                               goto error;
+               }
+
                key = context->user->uid_keyring;
                atomic_inc(&key->usage);
                key_ref = make_key_ref(key, 1);
                break;
 
        case KEY_SPEC_USER_SESSION_KEYRING:
+               if (!context->user->session_keyring) {
+                       ret = install_user_keyrings(context);
+                       if (ret < 0)
+                               goto error;
+               }
+
                key = context->user->session_keyring;
                atomic_inc(&key->usage);
                key_ref = make_key_ref(key, 1);
@@ -744,7 +768,7 @@ long join_session_keyring(const char *name)
        mutex_lock(&key_session_mutex);
 
        /* look for an existing keyring of this name */
-       keyring = find_keyring_by_name(name, 0);
+       keyring = find_keyring_by_name(name, false);
        if (PTR_ERR(keyring) == -ENOKEY) {
                /* not found - try and create a new one */
                keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk,
index 5ecc5057fb542c1bb9f914e72f4b95695d05dd70..ba32ca6469bdf2e74a8b0f9cb94d27604b7251af 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/kmod.h>
 #include <linux/err.h>
 #include <linux/keyctl.h>
+#include <linux/slab.h>
 #include "internal.h"
 
 /*
@@ -161,21 +162,22 @@ error_alloc:
  * call out to userspace for key construction
  * - we ignore program failure and go on key status instead
  */
-static int construct_key(struct key *key, const char *callout_info, void *aux)
+static int construct_key(struct key *key, const void *callout_info,
+                        size_t callout_len, void *aux)
 {
        struct key_construction *cons;
        request_key_actor_t actor;
        struct key *authkey;
        int ret;
 
-       kenter("%d,%s,%p", key->serial, callout_info, aux);
+       kenter("%d,%p,%zu,%p", key->serial, callout_info, callout_len, aux);
 
        cons = kmalloc(sizeof(*cons), GFP_KERNEL);
        if (!cons)
                return -ENOMEM;
 
        /* allocate an authorisation key */
-       authkey = request_key_auth_new(key, callout_info);
+       authkey = request_key_auth_new(key, callout_info, callout_len);
        if (IS_ERR(authkey)) {
                kfree(cons);
                ret = PTR_ERR(authkey);
@@ -331,6 +333,7 @@ alloc_failed:
 static struct key *construct_key_and_link(struct key_type *type,
                                          const char *description,
                                          const char *callout_info,
+                                         size_t callout_len,
                                          void *aux,
                                          struct key *dest_keyring,
                                          unsigned long flags)
@@ -348,7 +351,7 @@ static struct key *construct_key_and_link(struct key_type *type,
        key_user_put(user);
 
        if (ret == 0) {
-               ret = construct_key(key, callout_info, aux);
+               ret = construct_key(key, callout_info, callout_len, aux);
                if (ret < 0)
                        goto construction_failed;
        }
@@ -370,7 +373,8 @@ construction_failed:
  */
 struct key *request_key_and_link(struct key_type *type,
                                 const char *description,
-                                const char *callout_info,
+                                const void *callout_info,
+                                size_t callout_len,
                                 void *aux,
                                 struct key *dest_keyring,
                                 unsigned long flags)
@@ -378,8 +382,8 @@ struct key *request_key_and_link(struct key_type *type,
        struct key *key;
        key_ref_t key_ref;
 
-       kenter("%s,%s,%s,%p,%p,%lx",
-              type->name, description, callout_info, aux,
+       kenter("%s,%s,%p,%zu,%p,%p,%lx",
+              type->name, description, callout_info, callout_len, aux,
               dest_keyring, flags);
 
        /* search all the process keyrings for a key */
@@ -398,7 +402,8 @@ struct key *request_key_and_link(struct key_type *type,
                        goto error;
 
                key = construct_key_and_link(type, description, callout_info,
-                                            aux, dest_keyring, flags);
+                                            callout_len, aux, dest_keyring,
+                                            flags);
        }
 
 error:
@@ -434,10 +439,13 @@ struct key *request_key(struct key_type *type,
                        const char *callout_info)
 {
        struct key *key;
+       size_t callout_len = 0;
        int ret;
 
-       key = request_key_and_link(type, description, callout_info, NULL,
-                                  NULL, KEY_ALLOC_IN_QUOTA);
+       if (callout_info)
+               callout_len = strlen(callout_info);
+       key = request_key_and_link(type, description, callout_info, callout_len,
+                                  NULL, NULL, KEY_ALLOC_IN_QUOTA);
        if (!IS_ERR(key)) {
                ret = wait_for_key_construction(key, false);
                if (ret < 0) {
@@ -458,14 +466,15 @@ EXPORT_SYMBOL(request_key);
  */
 struct key *request_key_with_auxdata(struct key_type *type,
                                     const char *description,
-                                    const char *callout_info,
+                                    const void *callout_info,
+                                    size_t callout_len,
                                     void *aux)
 {
        struct key *key;
        int ret;
 
-       key = request_key_and_link(type, description, callout_info, aux,
-                                  NULL, KEY_ALLOC_IN_QUOTA);
+       key = request_key_and_link(type, description, callout_info, callout_len,
+                                  aux, NULL, KEY_ALLOC_IN_QUOTA);
        if (!IS_ERR(key)) {
                ret = wait_for_key_construction(key, false);
                if (ret < 0) {
@@ -485,10 +494,12 @@ EXPORT_SYMBOL(request_key_with_auxdata);
  */
 struct key *request_key_async(struct key_type *type,
                              const char *description,
-                             const char *callout_info)
+                             const void *callout_info,
+                             size_t callout_len)
 {
-       return request_key_and_link(type, description, callout_info, NULL,
-                                   NULL, KEY_ALLOC_IN_QUOTA);
+       return request_key_and_link(type, description, callout_info,
+                                   callout_len, NULL, NULL,
+                                   KEY_ALLOC_IN_QUOTA);
 }
 EXPORT_SYMBOL(request_key_async);
 
@@ -500,10 +511,11 @@ EXPORT_SYMBOL(request_key_async);
  */
 struct key *request_key_async_with_auxdata(struct key_type *type,
                                           const char *description,
-                                          const char *callout_info,
+                                          const void *callout_info,
+                                          size_t callout_len,
                                           void *aux)
 {
-       return request_key_and_link(type, description, callout_info, aux,
-                                   NULL, KEY_ALLOC_IN_QUOTA);
+       return request_key_and_link(type, description, callout_info,
+                                   callout_len, aux, NULL, KEY_ALLOC_IN_QUOTA);
 }
 EXPORT_SYMBOL(request_key_async_with_auxdata);
index e42b5252486fe07eb623f413ec61cc7073758da8..bd237b0a6331efffeff58b6ab6b300f823cd76aa 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/sched.h>
 #include <linux/err.h>
 #include <linux/seq_file.h>
+#include <linux/slab.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
@@ -61,7 +62,7 @@ static void request_key_auth_describe(const struct key *key,
 
        seq_puts(m, "key:");
        seq_puts(m, key->description);
-       seq_printf(m, " pid:%d ci:%zu", rka->pid, strlen(rka->callout_info));
+       seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len);
 
 } /* end request_key_auth_describe() */
 
@@ -77,7 +78,7 @@ static long request_key_auth_read(const struct key *key,
        size_t datalen;
        long ret;
 
-       datalen = strlen(rka->callout_info);
+       datalen = rka->callout_len;
        ret = datalen;
 
        /* we can return the data as is */
@@ -137,7 +138,8 @@ static void request_key_auth_destroy(struct key *key)
  * create an authorisation token for /sbin/request-key or whoever to gain
  * access to the caller's security data
  */
-struct key *request_key_auth_new(struct key *target, const char *callout_info)
+struct key *request_key_auth_new(struct key *target, const void *callout_info,
+                                size_t callout_len)
 {
        struct request_key_auth *rka, *irka;
        struct key *authkey = NULL;
@@ -152,7 +154,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
                kleave(" = -ENOMEM");
                return ERR_PTR(-ENOMEM);
        }
-       rka->callout_info = kmalloc(strlen(callout_info) + 1, GFP_KERNEL);
+       rka->callout_info = kmalloc(callout_len, GFP_KERNEL);
        if (!rka->callout_info) {
                kleave(" = -ENOMEM");
                kfree(rka);
@@ -186,7 +188,8 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
        }
 
        rka->target_key = key_get(target);
-       strcpy(rka->callout_info, callout_info);
+       memcpy(rka->callout_info, callout_info, callout_len);
+       rka->callout_len = callout_len;
 
        /* allocate the auth key */
        sprintf(desc, "%x", target->serial);
diff --git a/security/keys/sysctl.c b/security/keys/sysctl.c
new file mode 100644 (file)
index 0000000..b611d49
--- /dev/null
@@ -0,0 +1,50 @@
+/* Key management controls
+ *
+ * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/key.h>
+#include <linux/sysctl.h>
+#include "internal.h"
+
+ctl_table key_sysctls[] = {
+       {
+               .ctl_name = CTL_UNNUMBERED,
+               .procname = "maxkeys",
+               .data = &key_quota_maxkeys,
+               .maxlen = sizeof(unsigned),
+               .mode = 0644,
+               .proc_handler = &proc_dointvec,
+       },
+       {
+               .ctl_name = CTL_UNNUMBERED,
+               .procname = "maxbytes",
+               .data = &key_quota_maxbytes,
+               .maxlen = sizeof(unsigned),
+               .mode = 0644,
+               .proc_handler = &proc_dointvec,
+       },
+       {
+               .ctl_name = CTL_UNNUMBERED,
+               .procname = "root_maxkeys",
+               .data = &key_quota_root_maxkeys,
+               .maxlen = sizeof(unsigned),
+               .mode = 0644,
+               .proc_handler = &proc_dointvec,
+       },
+       {
+               .ctl_name = CTL_UNNUMBERED,
+               .procname = "root_maxbytes",
+               .data = &key_quota_root_maxbytes,
+               .maxlen = sizeof(unsigned),
+               .mode = 0644,
+               .proc_handler = &proc_dointvec,
+       },
+       { .ctl_name = 0 }
+};
index d5cb5898d96753e76cc62dfe0bbaae54f48f6000..59838a99b80e981d27ae892e7d3aa0204bb484c1 100644 (file)
@@ -491,23 +491,23 @@ void security_inode_delete(struct inode *inode)
        security_ops->inode_delete(inode);
 }
 
-int security_inode_setxattr(struct dentry *dentry, char *name,
-                            void *value, size_t size, int flags)
+int security_inode_setxattr(struct dentry *dentry, const char *name,
+                           const void *value, size_t size, int flags)
 {
        if (unlikely(IS_PRIVATE(dentry->d_inode)))
                return 0;
        return security_ops->inode_setxattr(dentry, name, value, size, flags);
 }
 
-void security_inode_post_setxattr(struct dentry *dentry, char *name,
-                                  void *value, size_t size, int flags)
+void security_inode_post_setxattr(struct dentry *dentry, const char *name,
+                                 const void *value, size_t size, int flags)
 {
        if (unlikely(IS_PRIVATE(dentry->d_inode)))
                return;
        security_ops->inode_post_setxattr(dentry, name, value, size, flags);
 }
 
-int security_inode_getxattr(struct dentry *dentry, char *name)
+int security_inode_getxattr(struct dentry *dentry, const char *name)
 {
        if (unlikely(IS_PRIVATE(dentry->d_inode)))
                return 0;
@@ -521,7 +521,7 @@ int security_inode_listxattr(struct dentry *dentry)
        return security_ops->inode_listxattr(dentry);
 }
 
-int security_inode_removexattr(struct dentry *dentry, char *name)
+int security_inode_removexattr(struct dentry *dentry, const char *name)
 {
        if (unlikely(IS_PRIVATE(dentry->d_inode)))
                return 0;
@@ -886,7 +886,7 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
 }
 EXPORT_SYMBOL(security_secid_to_secctx);
 
-int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
+int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
 {
        return security_ops->secctx_to_secid(secdata, seclen, secid);
 }
@@ -1156,6 +1156,11 @@ int security_key_permission(key_ref_t key_ref,
        return security_ops->key_permission(key_ref, context, perm);
 }
 
+int security_key_getsecurity(struct key *key, char **_buffer)
+{
+       return security_ops->key_getsecurity(key, _buffer);
+}
+
 #endif /* CONFIG_KEYS */
 
 #ifdef CONFIG_AUDIT
index 95a8ef4a5073fbcde9f2fcec8a5301cf7db27eb2..114b4b4c97b23b9acdf25e92d1b250f78167457d 100644 (file)
@@ -646,7 +646,7 @@ void avc_audit(u32 ssid, u32 tsid,
                                        if (*p)
                                                audit_log_untrustedstring(ab, p);
                                        else
-                                               audit_log_hex(ab, p, len);
+                                               audit_log_n_hex(ab, p, len);
                                        break;
                                }
                        }
index 04acb5af831749652b3aa41db0412c8706cea4c9..1b50a6ebc55fca85edaa9b7ef6256f31cc07ad4d 100644 (file)
@@ -2619,7 +2619,7 @@ static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
        return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
 }
 
-static int selinux_inode_setotherxattr(struct dentry *dentry, char *name)
+static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
 {
        if (!strncmp(name, XATTR_SECURITY_PREFIX,
                     sizeof XATTR_SECURITY_PREFIX - 1)) {
@@ -2638,7 +2638,8 @@ static int selinux_inode_setotherxattr(struct dentry *dentry, char *name)
        return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
 }
 
-static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
+static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
+                                 const void *value, size_t size, int flags)
 {
        struct task_security_struct *tsec = current->security;
        struct inode *inode = dentry->d_inode;
@@ -2687,8 +2688,9 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
                            &ad);
 }
 
-static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
-                                       void *value, size_t size, int flags)
+static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
+                                        const void *value, size_t size,
+                                       int flags)
 {
        struct inode *inode = dentry->d_inode;
        struct inode_security_struct *isec = inode->i_security;
@@ -2711,7 +2713,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
        return;
 }
 
-static int selinux_inode_getxattr(struct dentry *dentry, char *name)
+static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
 {
        return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
 }
@@ -2721,7 +2723,7 @@ static int selinux_inode_listxattr(struct dentry *dentry)
        return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
 }
 
-static int selinux_inode_removexattr(struct dentry *dentry, char *name)
+static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
 {
        if (strcmp(name, XATTR_NAME_SELINUX))
                return selinux_inode_setotherxattr(dentry, name);
@@ -3284,9 +3286,6 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
        if (rc)
                return rc;
 
-       if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info)))
-               return 0;
-
        if (!sig)
                perm = PROCESS__SIGNULL; /* null signal; existence test */
        else
@@ -5236,7 +5235,7 @@ static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
        return security_sid_to_context(secid, secdata, seclen);
 }
 
-static int selinux_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
+static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
 {
        return security_context_to_sid(secdata, seclen, secid);
 }
@@ -5298,6 +5297,20 @@ static int selinux_key_permission(key_ref_t key_ref,
                            SECCLASS_KEY, perm, NULL);
 }
 
+static int selinux_key_getsecurity(struct key *key, char **_buffer)
+{
+       struct key_security_struct *ksec = key->security;
+       char *context = NULL;
+       unsigned len;
+       int rc;
+
+       rc = security_sid_to_context(ksec->sid, &context, &len);
+       if (!rc)
+               rc = len;
+       *_buffer = context;
+       return rc;
+}
+
 #endif
 
 static struct security_operations selinux_ops = {
@@ -5486,6 +5499,7 @@ static struct security_operations selinux_ops = {
        .key_alloc =                    selinux_key_alloc,
        .key_free =                     selinux_key_free,
        .key_permission =               selinux_key_permission,
+       .key_getsecurity =              selinux_key_getsecurity,
 #endif
 
 #ifdef CONFIG_AUDIT
@@ -5534,14 +5548,6 @@ static __init int selinux_init(void)
        else
                printk(KERN_DEBUG "SELinux:  Starting in permissive mode\n");
 
-#ifdef CONFIG_KEYS
-       /* Add security information to initial keyrings */
-       selinux_key_alloc(&root_user_keyring, current,
-                         KEY_ALLOC_NOT_IN_QUOTA);
-       selinux_key_alloc(&root_session_keyring, current,
-                         KEY_ALLOC_NOT_IN_QUOTA);
-#endif
-
        return 0;
 }
 
index 6445b6440648ace1c03c2614f4bb5a860d3c546c..ad30ac4273d629b37e9f93ae2cbf143db36fc4f0 100644 (file)
@@ -93,10 +93,10 @@ int security_change_sid(u32 ssid, u32 tsid,
 int security_sid_to_context(u32 sid, char **scontext,
        u32 *scontext_len);
 
-int security_context_to_sid(char *scontext, u32 scontext_len,
+int security_context_to_sid(const char *scontext, u32 scontext_len,
        u32 *out_sid);
 
-int security_context_to_sid_default(char *scontext, u32 scontext_len,
+int security_context_to_sid_default(const char *scontext, u32 scontext_len,
                                    u32 *out_sid, u32 def_sid, gfp_t gfp_flags);
 
 int security_get_user_sids(u32 callsid, char *username,
index 2daaddbb301d27e549a372d88f26fb6b809c3900..dcc2e1c4fd83df58438bfd8592da112bfaa4b28d 100644 (file)
@@ -708,7 +708,7 @@ out:
 
 }
 
-static int security_context_to_sid_core(char *scontext, u32 scontext_len,
+static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
                                        u32 *sid, u32 def_sid, gfp_t gfp_flags)
 {
        char *scontext2;
@@ -835,7 +835,7 @@ out:
  * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
  * memory is available, or 0 on success.
  */
-int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
+int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid)
 {
        return security_context_to_sid_core(scontext, scontext_len,
                                            sid, SECSID_NULL, GFP_KERNEL);
@@ -858,8 +858,8 @@ int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
  * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
  * memory is available, or 0 on success.
  */
-int security_context_to_sid_default(char *scontext, u32 scontext_len, u32 *sid,
-                                   u32 def_sid, gfp_t gfp_flags)
+int security_context_to_sid_default(const char *scontext, u32 scontext_len,
+                                   u32 *sid, u32 def_sid, gfp_t gfp_flags)
 {
        return security_context_to_sid_core(scontext, scontext_len,
                                            sid, def_sid, gfp_flags);
index 77ec16a3b68baa800e1ffb2d429e0b10957337bf..b5c8f9237008618630d95cdf58ba945b06fe94d0 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/pipe_fs_i.h>
 #include <net/netlabel.h>
 #include <net/cipso_ipv4.h>
+#include <linux/audit.h>
 
 #include "smack.h"
 
@@ -574,8 +575,8 @@ static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
  *
  * Returns 0 if access is permitted, an error code otherwise
  */
-static int smack_inode_setxattr(struct dentry *dentry, char *name,
-                               void *value, size_t size, int flags)
+static int smack_inode_setxattr(struct dentry *dentry, const char *name,
+                               const void *value, size_t size, int flags)
 {
        int rc = 0;
 
@@ -604,8 +605,8 @@ static int smack_inode_setxattr(struct dentry *dentry, char *name,
  * Set the pointer in the inode blob to the entry found
  * in the master label list.
  */
-static void smack_inode_post_setxattr(struct dentry *dentry, char *name,
-                                     void *value, size_t size, int flags)
+static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
+                                     const void *value, size_t size, int flags)
 {
        struct inode_smack *isp;
        char *nsp;
@@ -641,7 +642,7 @@ static void smack_inode_post_setxattr(struct dentry *dentry, char *name,
  *
  * Returns 0 if access is permitted, an error code otherwise
  */
-static int smack_inode_getxattr(struct dentry *dentry, char *name)
+static int smack_inode_getxattr(struct dentry *dentry, const char *name)
 {
        return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ);
 }
@@ -655,7 +656,7 @@ static int smack_inode_getxattr(struct dentry *dentry, char *name)
  *
  * Returns 0 if access is permitted, an error code otherwise
  */
-static int smack_inode_removexattr(struct dentry *dentry, char *name)
+static int smack_inode_removexattr(struct dentry *dentry, const char *name)
 {
        int rc = 0;
 
@@ -752,6 +753,18 @@ static int smack_inode_listsecurity(struct inode *inode, char *buffer,
        return -EINVAL;
 }
 
+/**
+ * smack_inode_getsecid - Extract inode's security id
+ * @inode: inode to extract the info from
+ * @secid: where result will be saved
+ */
+static void smack_inode_getsecid(const struct inode *inode, u32 *secid)
+{
+       struct inode_smack *isp = inode->i_security;
+
+       *secid = smack_to_secid(isp->smk_inode);
+}
+
 /*
  * File Hooks
  */
@@ -1117,15 +1130,6 @@ static int smack_task_movememory(struct task_struct *p)
 static int smack_task_kill(struct task_struct *p, struct siginfo *info,
                           int sig, u32 secid)
 {
-       /*
-        * Special cases where signals really ought to go through
-        * in spite of policy. Stephen Smalley suggests it may
-        * make sense to change the caller so that it doesn't
-        * bother with the LSM hook in these cases.
-        */
-       if (info != SEND_SIG_NOINFO &&
-           (is_si_special(info) || SI_FROMKERNEL(info)))
-               return 0;
        /*
         * Sending a signal requires that the sender
         * can write the receiver.
@@ -1805,6 +1809,18 @@ static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag)
        return smk_curacc(isp, may);
 }
 
+/**
+ * smack_ipc_getsecid - Extract smack security id
+ * @ipcp: the object permissions
+ * @secid: where result will be saved
+ */
+static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid)
+{
+       char *smack = ipp->security;
+
+       *secid = smack_to_secid(smack);
+}
+
 /* module stacking operations */
 
 /**
@@ -2381,6 +2397,124 @@ static int smack_key_permission(key_ref_t key_ref,
 }
 #endif /* CONFIG_KEYS */
 
+/*
+ * Smack Audit hooks
+ *
+ * Audit requires a unique representation of each Smack specific
+ * rule. This unique representation is used to distinguish the
+ * object to be audited from remaining kernel objects and also
+ * works as a glue between the audit hooks.
+ *
+ * Since repository entries are added but never deleted, we'll use
+ * the smack_known label address related to the given audit rule as
+ * the needed unique representation. This also better fits the smack
+ * model where nearly everything is a label.
+ */
+#ifdef CONFIG_AUDIT
+
+/**
+ * smack_audit_rule_init - Initialize a smack audit rule
+ * @field: audit rule fields given from user-space (audit.h)
+ * @op: required testing operator (=, !=, >, <, ...)
+ * @rulestr: smack label to be audited
+ * @vrule: pointer to save our own audit rule representation
+ *
+ * Prepare to audit cases where (@field @op @rulestr) is true.
+ * The label to be audited is created if necessay.
+ */
+static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
+{
+       char **rule = (char **)vrule;
+       *rule = NULL;
+
+       if (field != AUDIT_SUBJ_USER && field != AUDIT_OBJ_USER)
+               return -EINVAL;
+
+       if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL)
+               return -EINVAL;
+
+       *rule = smk_import(rulestr, 0);
+
+       return 0;
+}
+
+/**
+ * smack_audit_rule_known - Distinguish Smack audit rules
+ * @krule: rule of interest, in Audit kernel representation format
+ *
+ * This is used to filter Smack rules from remaining Audit ones.
+ * If it's proved that this rule belongs to us, the
+ * audit_rule_match hook will be called to do the final judgement.
+ */
+static int smack_audit_rule_known(struct audit_krule *krule)
+{
+       struct audit_field *f;
+       int i;
+
+       for (i = 0; i < krule->field_count; i++) {
+               f = &krule->fields[i];
+
+               if (f->type == AUDIT_SUBJ_USER || f->type == AUDIT_OBJ_USER)
+                       return 1;
+       }
+
+       return 0;
+}
+
+/**
+ * smack_audit_rule_match - Audit given object ?
+ * @secid: security id for identifying the object to test
+ * @field: audit rule flags given from user-space
+ * @op: required testing operator
+ * @vrule: smack internal rule presentation
+ * @actx: audit context associated with the check
+ *
+ * The core Audit hook. It's used to take the decision of
+ * whether to audit or not to audit a given object.
+ */
+static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule,
+                                 struct audit_context *actx)
+{
+       char *smack;
+       char *rule = vrule;
+
+       if (!rule) {
+               audit_log(actx, GFP_KERNEL, AUDIT_SELINUX_ERR,
+                         "Smack: missing rule\n");
+               return -ENOENT;
+       }
+
+       if (field != AUDIT_SUBJ_USER && field != AUDIT_OBJ_USER)
+               return 0;
+
+       smack = smack_from_secid(secid);
+
+       /*
+        * No need to do string comparisons. If a match occurs,
+        * both pointers will point to the same smack_known
+        * label.
+        */
+       if (op == AUDIT_EQUAL)
+               return (rule == smack);
+       if (op == AUDIT_NOT_EQUAL)
+               return (rule != smack);
+
+       return 0;
+}
+
+/**
+ * smack_audit_rule_free - free smack rule representation
+ * @vrule: rule to be freed.
+ *
+ * No memory was allocated.
+ */
+static void smack_audit_rule_free(void *vrule)
+{
+       /* No-op */
+}
+
+#endif /* CONFIG_AUDIT */
+
 /*
  * smack_secid_to_secctx - return the smack label for a secid
  * @secid: incoming integer
@@ -2406,7 +2540,7 @@ static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
  *
  * Exists for audit and networking code.
  */
-static int smack_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
+static int smack_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
 {
        *secid = smack_to_secid(secdata);
        return 0;
@@ -2467,6 +2601,7 @@ struct security_operations smack_ops = {
        .inode_getsecurity =            smack_inode_getsecurity,
        .inode_setsecurity =            smack_inode_setsecurity,
        .inode_listsecurity =           smack_inode_listsecurity,
+       .inode_getsecid =               smack_inode_getsecid,
 
        .file_permission =              smack_file_permission,
        .file_alloc_security =          smack_file_alloc_security,
@@ -2498,6 +2633,7 @@ struct security_operations smack_ops = {
        .task_prctl =                   cap_task_prctl,
 
        .ipc_permission =               smack_ipc_permission,
+       .ipc_getsecid =                 smack_ipc_getsecid,
 
        .msg_msg_alloc_security =       smack_msg_msg_alloc_security,
        .msg_msg_free_security =        smack_msg_msg_free_security,
@@ -2542,12 +2678,22 @@ struct security_operations smack_ops = {
        .sk_free_security =             smack_sk_free_security,
        .sock_graft =                   smack_sock_graft,
        .inet_conn_request =            smack_inet_conn_request,
+
  /* key management security hooks */
 #ifdef CONFIG_KEYS
        .key_alloc =                    smack_key_alloc,
        .key_free =                     smack_key_free,
        .key_permission =               smack_key_permission,
 #endif /* CONFIG_KEYS */
+
+ /* Audit hooks */
+#ifdef CONFIG_AUDIT
+       .audit_rule_init =              smack_audit_rule_init,
+       .audit_rule_known =             smack_audit_rule_known,
+       .audit_rule_match =             smack_audit_rule_match,
+       .audit_rule_free =              smack_audit_rule_free,
+#endif /* CONFIG_AUDIT */
+
        .secid_to_secctx =              smack_secid_to_secctx,
        .secctx_to_secid =              smack_secctx_to_secid,
        .release_secctx =               smack_release_secctx,
index a5da5a8cfe9b546ac4f1fd3431d716128440915a..271a835fbbe3f72f4e5465cbf84b9b271fa7e77a 100644 (file)
@@ -324,6 +324,7 @@ static void smk_cipso_doi(void)
        struct netlbl_audit audit_info;
 
        audit_info.loginuid = audit_get_loginuid(current);
+       audit_info.sessionid = audit_get_sessionid(current);
        audit_info.secid = smack_to_secid(current->security);
 
        rc = netlbl_cfg_map_del(NULL, &audit_info);
@@ -356,6 +357,7 @@ static void smk_unlbl_ambient(char *oldambient)
        struct netlbl_audit audit_info;
 
        audit_info.loginuid = audit_get_loginuid(current);
+       audit_info.sessionid = audit_get_sessionid(current);
        audit_info.secid = smack_to_secid(current->security);
 
        if (oldambient != NULL) {
index 9977ec2eace35d547772db031c0db29bed15fe37..cb5ead3e202df5512317aeba7e5c281d993f8fae 100644 (file)
@@ -544,7 +544,7 @@ int __init snd_info_init(void)
 {
        struct proc_dir_entry *p;
 
-       p = snd_create_proc_entry("asound", S_IFDIR | S_IRUGO | S_IXUGO, &proc_root);
+       p = snd_create_proc_entry("asound", S_IFDIR | S_IRUGO | S_IXUGO, NULL);
        if (p == NULL)
                return -ENOMEM;
        snd_proc_root = p;
@@ -594,7 +594,7 @@ int __exit snd_info_done(void)
 #ifdef CONFIG_SND_OSSEMUL
                snd_info_free_entry(snd_oss_root);
 #endif
-               snd_remove_proc_entry(&proc_root, snd_proc_root);
+               snd_remove_proc_entry(NULL, snd_proc_root);
        }
        return 0;
 }
index 920e5780c2284c9c086dd1bfaf02aff5462786d2..23b7bc02728b44ac9ad1086a827ffd3b917418ea 100644 (file)
@@ -629,9 +629,8 @@ static const struct file_operations snd_mem_proc_fops = {
 static int __init snd_mem_init(void)
 {
 #ifdef CONFIG_PROC_FS
-       snd_mem_proc = create_proc_entry(SND_MEM_PROC_FILE, 0644, NULL);
-       if (snd_mem_proc)
-               snd_mem_proc->proc_fops = &snd_mem_proc_fops;
+       snd_mem_proc = proc_create(SND_MEM_PROC_FILE, 0644, NULL,
+                                  &snd_mem_proc_fops);
 #endif
        return 0;
 }
index fe85af1c56934ab58ecbb0fda39d92b4f60753c8..a78a8d045175bb65b4dc576612e289b36957b898 100644 (file)
@@ -8,6 +8,8 @@ config SND_PCSP
        tristate "Internal PC speaker support"
        depends on X86_PC && HIGH_RES_TIMERS
        depends on INPUT
+       depends on SND
+       select SND_PCM
        help
          If you don't have a sound card in your computer, you can include a
          driver for the PC speaker which allows it to act like a primitive
index 18cca2457d44c1164978cc2453531396d8b38b0a..2af09996a3d01a39d4b913a23c1d08855ed54f06 100644 (file)
@@ -243,7 +243,7 @@ static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd,
 #endif
        }
        mpu->write(mpu, cmd, MPU401C(mpu));
-       if (ack) {
+       if (ack && !(mpu->info_flags & MPU401_INFO_NO_ACK)) {
                ok = 0;
                timeout = 10000;
                while (!ok && timeout-- > 0) {
index cdda64b02f4688c638f09b169bf0aefb1799a156..d9783a4263e0bee2a8ae47e01eb7e063e7dea51b 100644 (file)
@@ -60,6 +60,7 @@ enum {
        ALC880_TCL_S700,
        ALC880_LG,
        ALC880_LG_LW,
+       ALC880_MEDION_RIM,
 #ifdef CONFIG_SND_DEBUG
        ALC880_TEST,
 #endif
@@ -2275,6 +2276,75 @@ static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res)
                alc880_lg_lw_automute(codec);
 }
 
+static struct snd_kcontrol_new alc880_medion_rim_mixer[] = {
+       HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+       HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
+       HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+       HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+       HDA_CODEC_MUTE("Internal Playback Switch", 0x0b, 0x1, HDA_INPUT),
+       { } /* end */
+};
+
+static struct hda_input_mux alc880_medion_rim_capture_source = {
+       .num_items = 2,
+       .items = {
+               { "Mic", 0x0 },
+               { "Internal Mic", 0x1 },
+       },
+};
+
+static struct hda_verb alc880_medion_rim_init_verbs[] = {
+       {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+
+       {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+       /* Mic1 (rear panel) pin widget for input and vref at 80% */
+       {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+       {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* Mic2 (as headphone out) for HP output */
+       {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+       {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+       /* Internal Speaker */
+       {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+       {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
+       {0x20, AC_VERB_SET_PROC_COEF,  0x3060},
+
+       {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+       { }
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc880_medion_rim_automute(struct hda_codec *codec)
+{
+       unsigned int present;
+       unsigned char bits;
+
+       present = snd_hda_codec_read(codec, 0x14, 0,
+                                    AC_VERB_GET_PIN_SENSE, 0)
+               & AC_PINSENSE_PRESENCE;
+       bits = present ? HDA_AMP_MUTE : 0;
+       snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0,
+                                HDA_AMP_MUTE, bits);
+       if (present)
+               snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
+       else
+               snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 2);
+}
+
+static void alc880_medion_rim_unsol_event(struct hda_codec *codec,
+                                         unsigned int res)
+{
+       /* Looks like the unsol event is incompatible with the standard
+        * definition.  4bit tag is placed at 28 bit!
+        */
+       if ((res >> 28) == ALC880_HP_EVENT)
+               alc880_medion_rim_automute(codec);
+}
+
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 static struct hda_amp_list alc880_loopbacks[] = {
        { 0x0b, HDA_INPUT, 0 },
@@ -2882,6 +2952,7 @@ static const char *alc880_models[ALC880_MODEL_LAST] = {
        [ALC880_F1734]          = "F1734",
        [ALC880_LG]             = "lg",
        [ALC880_LG_LW]          = "lg-lw",
+       [ALC880_MEDION_RIM]     = "medion",
 #ifdef CONFIG_SND_DEBUG
        [ALC880_TEST]           = "test",
 #endif
@@ -2933,6 +3004,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),
        SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),
        SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),
+       SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_MEDION_RIM),
        SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG),
        SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),
        SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),
@@ -3227,6 +3299,20 @@ static struct alc_config_preset alc880_presets[] = {
                .unsol_event = alc880_lg_lw_unsol_event,
                .init_hook = alc880_lg_lw_automute,
        },
+       [ALC880_MEDION_RIM] = {
+               .mixers = { alc880_medion_rim_mixer },
+               .init_verbs = { alc880_volume_init_verbs,
+                               alc880_medion_rim_init_verbs,
+                               alc_gpio2_init_verbs },
+               .num_dacs = ARRAY_SIZE(alc880_dac_nids),
+               .dac_nids = alc880_dac_nids,
+               .dig_out_nid = ALC880_DIGOUT_NID,
+               .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
+               .channel_mode = alc880_2_jack_modes,
+               .input_mux = &alc880_medion_rim_capture_source,
+               .unsol_event = alc880_medion_rim_unsol_event,
+               .init_hook = alc880_medion_rim_automute,
+       },
 #ifdef CONFIG_SND_DEBUG
        [ALC880_TEST] = {
                .mixers = { alc880_test_mixer },
index 4490422fb930bc047af5df27cad62266e3a55689..67350901772ce986582ef19e0b8ce9dad738f9cb 100644 (file)
@@ -2429,6 +2429,7 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
                        if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712,
                                                       ICEREG1724(ice, MPU_CTRL),
                                                       (MPU401_INFO_INTEGRATED |
+                                                       MPU401_INFO_NO_ACK |
                                                        MPU401_INFO_TX_IRQ),
                                                       ice->irq, 0,
                                                       &ice->rmidi[0])) < 0) {
@@ -2442,12 +2443,10 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
                        outb(inb(ICEREG1724(ice, IRQMASK)) &
                             ~(VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX),
                             ICEREG1724(ice, IRQMASK));
-#if 0 /* for testing */
                        /* set watermarks */
                        outb(VT1724_MPU_RX_FIFO | 0x1,
                             ICEREG1724(ice, MPU_FIFO_WM));
                        outb(0x1, ICEREG1724(ice, MPU_FIFO_WM));
-#endif
                }
        }
 
index d49417bf78c693dc115390cd14d6c54d84fd8c7f..9ca1133261437f7f7d630e4e2276b9af9d068e1c 100644 (file)
@@ -663,7 +663,7 @@ static int __init aica_init(void)
                return err;
        pd = platform_device_register_simple(SND_AICA_DRIVER, -1,
                                             aica_memory_space, 2);
-       if (unlikely(IS_ERR(pd))) {
+       if (IS_ERR(pd)) {
                platform_driver_unregister(&snd_aica_driver);
                return PTR_ERR(pd);
        }
index a3b51df2bea148293bb5f12b55e47ee42936d45f..18f28ac4bfe82997733df97c1c1eaaf05dc41adb 100644 (file)
@@ -30,6 +30,7 @@ source "sound/soc/s3c24xx/Kconfig"
 source "sound/soc/sh/Kconfig"
 source "sound/soc/fsl/Kconfig"
 source "sound/soc/davinci/Kconfig"
+source "sound/soc/omap/Kconfig"
 
 # Supported codecs
 source "sound/soc/codecs/Kconfig"
index e489dbdde45839664cbf44dd408143afce2374e2..782db2127108fd26c19a0bb6bf2ee378cbd4d0ac 100644 (file)
@@ -1,4 +1,4 @@
 snd-soc-core-objs := soc-core.o soc-dapm.o
 
 obj-$(CONFIG_SND_SOC)  += snd-soc-core.o
-obj-$(CONFIG_SND_SOC)  += codecs/ at91/ pxa/ s3c24xx/ sh/ fsl/ davinci/
+obj-$(CONFIG_SND_SOC)  += codecs/ at91/ pxa/ s3c24xx/ sh/ fsl/ davinci/ omap/
index d2d79e182a45b1bc44c79e6278043a0ae147a9cf..76c1e2d33e7d0b8d0b5d22a6dd7dc5fbf7fa37f6 100644 (file)
@@ -37,23 +37,23 @@ static int ac97_write(struct snd_soc_codec *codec,
  * WM9712 register cache
  */
 static const u16 wm9712_reg[] = {
-       0x6174, 0x8000, 0x8000, 0x8000, // 6
-       0x0f0f, 0xaaa0, 0xc008, 0x6808, // e
-       0xe808, 0xaaa0, 0xad00, 0x8000, // 16
-       0xe808, 0x3000, 0x8000, 0x0000, // 1e
-       0x0000, 0x0000, 0x0000, 0x000f, // 26
-       0x0405, 0x0410, 0xbb80, 0xbb80, // 2e
-       0x0000, 0xbb80, 0x0000, 0x0000, // 36
-       0x0000, 0x2000, 0x0000, 0x0000, // 3e
-       0x0000, 0x0000, 0x0000, 0x0000, // 46
-       0x0000, 0x0000, 0xf83e, 0xffff, // 4e
-       0x0000, 0x0000, 0x0000, 0xf83e, // 56
-       0x0008, 0x0000, 0x0000, 0x0000, // 5e
-       0xb032, 0x3e00, 0x0000, 0x0000, // 66
-       0x0000, 0x0000, 0x0000, 0x0000, // 6e
-       0x0000, 0x0000, 0x0000, 0x0006, // 76
-       0x0001, 0x0000, 0x574d, 0x4c12, // 7e
-       0x0000, 0x0000 // virtual hp mixers
+       0x6174, 0x8000, 0x8000, 0x8000, /*  6 */
+       0x0f0f, 0xaaa0, 0xc008, 0x6808, /*  e */
+       0xe808, 0xaaa0, 0xad00, 0x8000, /* 16 */
+       0xe808, 0x3000, 0x8000, 0x0000, /* 1e */
+       0x0000, 0x0000, 0x0000, 0x000f, /* 26 */
+       0x0405, 0x0410, 0xbb80, 0xbb80, /* 2e */
+       0x0000, 0xbb80, 0x0000, 0x0000, /* 36 */
+       0x0000, 0x2000, 0x0000, 0x0000, /* 3e */
+       0x0000, 0x0000, 0x0000, 0x0000, /* 46 */
+       0x0000, 0x0000, 0xf83e, 0xffff, /* 4e */
+       0x0000, 0x0000, 0x0000, 0xf83e, /* 56 */
+       0x0008, 0x0000, 0x0000, 0x0000, /* 5e */
+       0xb032, 0x3e00, 0x0000, 0x0000, /* 66 */
+       0x0000, 0x0000, 0x0000, 0x0000, /* 6e */
+       0x0000, 0x0000, 0x0000, 0x0006, /* 76 */
+       0x0001, 0x0000, 0x574d, 0x4c12, /* 7e */
+       0x0000, 0x0000 /* virtual hp mixers */
 };
 
 /* virtual HP mixers regs */
@@ -94,7 +94,7 @@ static const struct snd_kcontrol_new wm9712_snd_ac97_controls[] = {
 SOC_DOUBLE("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1),
 SOC_SINGLE("Speaker Playback Switch", AC97_MASTER, 15, 1, 1),
 SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1),
-SOC_SINGLE("Headphone Playback Switch", AC97_HEADPHONE,15, 1, 1),
+SOC_SINGLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 1, 1),
 SOC_DOUBLE("PCM Playback Volume", AC97_PCM, 8, 0, 31, 1),
 
 SOC_SINGLE("Speaker Playback ZC Switch", AC97_MASTER, 7, 1, 0),
@@ -165,7 +165,8 @@ static int wm9712_add_controls(struct snd_soc_codec *codec)
 
        for (i = 0; i < ARRAY_SIZE(wm9712_snd_ac97_controls); i++) {
                err = snd_ctl_add(codec->card,
-                               snd_soc_cnew(&wm9712_snd_ac97_controls[i],codec, NULL));
+                                 snd_soc_cnew(&wm9712_snd_ac97_controls[i],
+                                              codec, NULL));
                if (err < 0)
                        return err;
        }
@@ -363,7 +364,6 @@ static const char *audio_map[][3] = {
        {"Left HP Mixer", "PCM Playback Switch",  "Left DAC"},
        {"Left HP Mixer", "Mic Sidetone Switch",  "Mic PGA"},
        {"Left HP Mixer", NULL,  "ALC Sidetone Mux"},
-       //{"Right HP Mixer", NULL, "HP Mixer"},
 
        /* Right HP mixer */
        {"Right HP Mixer", "PCBeep Bypass Switch", "PCBEEP"},
@@ -454,15 +454,13 @@ static int wm9712_add_widgets(struct snd_soc_codec *codec)
 {
        int i;
 
-       for(i = 0; i < ARRAY_SIZE(wm9712_dapm_widgets); i++) {
+       for (i = 0; i < ARRAY_SIZE(wm9712_dapm_widgets); i++)
                snd_soc_dapm_new_control(codec, &wm9712_dapm_widgets[i]);
-       }
 
-       /* set up audio path audio_mapnects */
-       for(i = 0; audio_map[i][0] != NULL; i++) {
+       /* set up audio path connects */
+       for (i = 0; audio_map[i][0] != NULL; i++)
                snd_soc_dapm_connect_input(codec, audio_map[i][0],
-                       audio_map[i][1], audio_map[i][2]);
-       }
+                                          audio_map[i][1], audio_map[i][2]);
 
        snd_soc_dapm_new_widgets(codec);
        return 0;
@@ -540,7 +538,8 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream)
 }
 
 #define WM9712_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
-               SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
+               SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
+               SNDRV_PCM_RATE_48000)
 
 struct snd_soc_codec_dai wm9712_dai[] = {
 {
@@ -577,8 +576,6 @@ EXPORT_SYMBOL_GPL(wm9712_dai);
 
 static int wm9712_dapm_event(struct snd_soc_codec *codec, int event)
 {
-       u16 reg;
-
        switch (event) {
        case SNDRV_CTL_POWER_D0: /* full On */
        case SNDRV_CTL_POWER_D1: /* partial On */
@@ -633,7 +630,7 @@ static int wm9712_soc_resume(struct platform_device *pdev)
        u16 *cache = codec->reg_cache;
 
        ret = wm9712_reset(codec, 1);
-       if (ret < 0){
+       if (ret < 0) {
                printk(KERN_ERR "could not reset AC97 codec\n");
                return ret;
        }
@@ -642,9 +639,9 @@ static int wm9712_soc_resume(struct platform_device *pdev)
 
        if (ret == 0) {
                /* Sync reg_cache with the hardware after cold reset */
-               for (i = 2; i < ARRAY_SIZE(wm9712_reg) << 1; i+=2) {
+               for (i = 2; i < ARRAY_SIZE(wm9712_reg) << 1; i += 2) {
                        if (i == AC97_INT_PAGING || i == AC97_POWERDOWN ||
-                               (i > 0x58 && i != 0x5c))
+                           (i > 0x58 && i != 0x5c))
                                continue;
                        soc_ac97_ops.write(codec->ac97, i, cache[i>>1]);
                }
@@ -757,7 +754,6 @@ struct snd_soc_codec_device soc_codec_dev_wm9712 = {
        .suspend =      wm9712_soc_suspend,
        .resume =       wm9712_soc_resume,
 };
-
 EXPORT_SYMBOL_GPL(soc_codec_dev_wm9712);
 
 MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver");
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
new file mode 100644 (file)
index 0000000..0230d83
--- /dev/null
@@ -0,0 +1,19 @@
+menu "SoC Audio for the Texas Instruments OMAP"
+
+config SND_OMAP_SOC
+       tristate "SoC Audio for the Texas Instruments OMAP chips"
+       depends on ARCH_OMAP && SND_SOC
+
+config SND_OMAP_SOC_MCBSP
+       tristate
+       select OMAP_MCBSP
+
+config SND_OMAP_SOC_N810
+       tristate "SoC Audio support for Nokia N810"
+       depends on SND_OMAP_SOC && MACH_NOKIA_N810
+       select SND_OMAP_SOC_MCBSP
+       select SND_SOC_TLV320AIC3X
+       help
+         Say Y if you want to add support for SoC audio on Nokia N810.
+
+endmenu
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
new file mode 100644 (file)
index 0000000..d8d8d58
--- /dev/null
@@ -0,0 +1,11 @@
+# OMAP Platform Support
+snd-soc-omap-objs := omap-pcm.o
+snd-soc-omap-mcbsp-objs := omap-mcbsp.o
+
+obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o
+obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
+
+# OMAP Machine Support
+snd-soc-n810-objs := n810.o
+
+obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
new file mode 100644 (file)
index 0000000..83b1eb4
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+ * n810.c  --  SoC audio for Nokia N810
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Contact: Jarkko Nikula <jarkko.nikula@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+#include "../codecs/tlv320aic3x.h"
+
+#define RX44_HEADSET_AMP_GPIO  10
+#define RX44_SPEAKER_AMP_GPIO  101
+
+static struct clk *sys_clkout2;
+static struct clk *sys_clkout2_src;
+static struct clk *func96m_clk;
+
+static int n810_spk_func;
+static int n810_jack_func;
+
+static void n810_ext_control(struct snd_soc_codec *codec)
+{
+       snd_soc_dapm_set_endpoint(codec, "Ext Spk", n810_spk_func);
+       snd_soc_dapm_set_endpoint(codec, "Headphone Jack", n810_jack_func);
+
+       snd_soc_dapm_sync_endpoints(codec);
+}
+
+static int n810_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_codec *codec = rtd->socdev->codec;
+
+       n810_ext_control(codec);
+       return clk_enable(sys_clkout2);
+}
+
+static void n810_shutdown(struct snd_pcm_substream *substream)
+{
+       clk_disable(sys_clkout2);
+}
+
+static int n810_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       int err;
+
+       /* Set codec DAI configuration */
+       err = codec_dai->dai_ops.set_fmt(codec_dai,
+                                        SND_SOC_DAIFMT_I2S |
+                                        SND_SOC_DAIFMT_NB_NF |
+                                        SND_SOC_DAIFMT_CBM_CFM);
+       if (err < 0)
+               return err;
+
+       /* Set cpu DAI configuration */
+       err = cpu_dai->dai_ops.set_fmt(cpu_dai,
+                                      SND_SOC_DAIFMT_I2S |
+                                      SND_SOC_DAIFMT_NB_NF |
+                                      SND_SOC_DAIFMT_CBM_CFM);
+       if (err < 0)
+               return err;
+
+       /* Set the codec system clock for DAC and ADC */
+       err = codec_dai->dai_ops.set_sysclk(codec_dai, 0, 12000000,
+                                           SND_SOC_CLOCK_IN);
+
+       return err;
+}
+
+static struct snd_soc_ops n810_ops = {
+       .startup = n810_startup,
+       .hw_params = n810_hw_params,
+       .shutdown = n810_shutdown,
+};
+
+static int n810_get_spk(struct snd_kcontrol *kcontrol,
+                       struct snd_ctl_elem_value *ucontrol)
+{
+       ucontrol->value.integer.value[0] = n810_spk_func;
+
+       return 0;
+}
+
+static int n810_set_spk(struct snd_kcontrol *kcontrol,
+                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+
+       if (n810_spk_func == ucontrol->value.integer.value[0])
+               return 0;
+
+       n810_spk_func = ucontrol->value.integer.value[0];
+       n810_ext_control(codec);
+
+       return 1;
+}
+
+static int n810_get_jack(struct snd_kcontrol *kcontrol,
+                        struct snd_ctl_elem_value *ucontrol)
+{
+       ucontrol->value.integer.value[0] = n810_jack_func;
+
+       return 0;
+}
+
+static int n810_set_jack(struct snd_kcontrol *kcontrol,
+                        struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+
+       if (n810_jack_func == ucontrol->value.integer.value[0])
+               return 0;
+
+       n810_jack_func = ucontrol->value.integer.value[0];
+       n810_ext_control(codec);
+
+       return 1;
+}
+
+static int n810_spk_event(struct snd_soc_dapm_widget *w,
+                         struct snd_kcontrol *k, int event)
+{
+       if (SND_SOC_DAPM_EVENT_ON(event))
+               omap_set_gpio_dataout(RX44_SPEAKER_AMP_GPIO, 1);
+       else
+               omap_set_gpio_dataout(RX44_SPEAKER_AMP_GPIO, 0);
+
+       return 0;
+}
+
+static int n810_jack_event(struct snd_soc_dapm_widget *w,
+                          struct snd_kcontrol *k, int event)
+{
+       if (SND_SOC_DAPM_EVENT_ON(event))
+               omap_set_gpio_dataout(RX44_HEADSET_AMP_GPIO, 1);
+       else
+               omap_set_gpio_dataout(RX44_HEADSET_AMP_GPIO, 0);
+
+       return 0;
+}
+
+static const struct snd_soc_dapm_widget aic33_dapm_widgets[] = {
+       SND_SOC_DAPM_SPK("Ext Spk", n810_spk_event),
+       SND_SOC_DAPM_HP("Headphone Jack", n810_jack_event),
+};
+
+static const char *audio_map[][3] = {
+       {"Headphone Jack", NULL, "HPLOUT"},
+       {"Headphone Jack", NULL, "HPROUT"},
+
+       {"Ext Spk", NULL, "LLOUT"},
+       {"Ext Spk", NULL, "RLOUT"},
+};
+
+static const char *spk_function[] = {"Off", "On"};
+static const char *jack_function[] = {"Off", "Headphone"};
+static const struct soc_enum n810_enum[] = {
+       SOC_ENUM_SINGLE_EXT(2, spk_function),
+       SOC_ENUM_SINGLE_EXT(3, jack_function),
+};
+
+static const struct snd_kcontrol_new aic33_n810_controls[] = {
+       SOC_ENUM_EXT("Speaker Function", n810_enum[0],
+                    n810_get_spk, n810_set_spk),
+       SOC_ENUM_EXT("Jack Function", n810_enum[1],
+                    n810_get_jack, n810_set_jack),
+};
+
+static int n810_aic33_init(struct snd_soc_codec *codec)
+{
+       int i, err;
+
+       /* Not connected */
+       snd_soc_dapm_set_endpoint(codec, "MONO_LOUT", 0);
+       snd_soc_dapm_set_endpoint(codec, "HPLCOM", 0);
+       snd_soc_dapm_set_endpoint(codec, "HPRCOM", 0);
+
+       /* Add N810 specific controls */
+       for (i = 0; i < ARRAY_SIZE(aic33_n810_controls); i++) {
+               err = snd_ctl_add(codec->card,
+                       snd_soc_cnew(&aic33_n810_controls[i], codec, NULL));
+               if (err < 0)
+                       return err;
+       }
+
+       /* Add N810 specific widgets */
+       for (i = 0; i < ARRAY_SIZE(aic33_dapm_widgets); i++)
+               snd_soc_dapm_new_control(codec, &aic33_dapm_widgets[i]);
+
+       /* Set up N810 specific audio path audio_map */
+       for (i = 0; i < ARRAY_SIZE(audio_map); i++)
+               snd_soc_dapm_connect_input(codec, audio_map[i][0],
+                       audio_map[i][1], audio_map[i][2]);
+
+       snd_soc_dapm_sync_endpoints(codec);
+
+       return 0;
+}
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link n810_dai = {
+       .name = "TLV320AIC33",
+       .stream_name = "AIC33",
+       .cpu_dai = &omap_mcbsp_dai[0],
+       .codec_dai = &aic3x_dai,
+       .init = n810_aic33_init,
+       .ops = &n810_ops,
+};
+
+/* Audio machine driver */
+static struct snd_soc_machine snd_soc_machine_n810 = {
+       .name = "N810",
+       .dai_link = &n810_dai,
+       .num_links = 1,
+};
+
+/* Audio private data */
+static struct aic3x_setup_data n810_aic33_setup = {
+       .i2c_address = 0x18,
+};
+
+/* Audio subsystem */
+static struct snd_soc_device n810_snd_devdata = {
+       .machine = &snd_soc_machine_n810,
+       .platform = &omap_soc_platform,
+       .codec_dev = &soc_codec_dev_aic3x,
+       .codec_data = &n810_aic33_setup,
+};
+
+static struct platform_device *n810_snd_device;
+
+static int __init n810_soc_init(void)
+{
+       int err;
+       struct device *dev;
+
+       if (!machine_is_nokia_n810())
+               return -ENODEV;
+
+       n810_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!n810_snd_device)
+               return -ENOMEM;
+
+       platform_set_drvdata(n810_snd_device, &n810_snd_devdata);
+       n810_snd_devdata.dev = &n810_snd_device->dev;
+       *(unsigned int *)n810_dai.cpu_dai->private_data = 1; /* McBSP2 */
+       err = platform_device_add(n810_snd_device);
+       if (err)
+               goto err1;
+
+       dev = &n810_snd_device->dev;
+
+       sys_clkout2_src = clk_get(dev, "sys_clkout2_src");
+       if (IS_ERR(sys_clkout2_src)) {
+               dev_err(dev, "Could not get sys_clkout2_src clock\n");
+               return -ENODEV;
+       }
+       sys_clkout2 = clk_get(dev, "sys_clkout2");
+       if (IS_ERR(sys_clkout2)) {
+               dev_err(dev, "Could not get sys_clkout2\n");
+               goto err1;
+       }
+       /*
+        * Configure 12 MHz output on SYS_CLKOUT2. Therefore we must use
+        * 96 MHz as its parent in order to get 12 MHz
+        */
+       func96m_clk = clk_get(dev, "func_96m_ck");
+       if (IS_ERR(func96m_clk)) {
+               dev_err(dev, "Could not get func 96M clock\n");
+               goto err2;
+       }
+       clk_set_parent(sys_clkout2_src, func96m_clk);
+       clk_set_rate(sys_clkout2, 12000000);
+
+       if (omap_request_gpio(RX44_HEADSET_AMP_GPIO) < 0)
+               BUG();
+       if (omap_request_gpio(RX44_SPEAKER_AMP_GPIO) < 0)
+               BUG();
+       omap_set_gpio_direction(RX44_HEADSET_AMP_GPIO, 0);
+       omap_set_gpio_direction(RX44_SPEAKER_AMP_GPIO, 0);
+
+       return 0;
+err2:
+       clk_put(sys_clkout2);
+       platform_device_del(n810_snd_device);
+err1:
+       platform_device_put(n810_snd_device);
+
+       return err;
+
+}
+
+static void __exit n810_soc_exit(void)
+{
+       platform_device_unregister(n810_snd_device);
+}
+
+module_init(n810_soc_init);
+module_exit(n810_soc_exit);
+
+MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
+MODULE_DESCRIPTION("ALSA SoC Nokia N810");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
new file mode 100644 (file)
index 0000000..40d87e6
--- /dev/null
@@ -0,0 +1,414 @@
+/*
+ * omap-mcbsp.c  --  OMAP ALSA SoC DAI driver using McBSP port
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Contact: Jarkko Nikula <jarkko.nikula@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <asm/arch/control.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/mcbsp.h>
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+
+#define OMAP_MCBSP_RATES       (SNDRV_PCM_RATE_44100 | \
+                                SNDRV_PCM_RATE_48000 | \
+                                SNDRV_PCM_RATE_KNOT)
+
+struct omap_mcbsp_data {
+       unsigned int                    bus_id;
+       struct omap_mcbsp_reg_cfg       regs;
+       /*
+        * Flags indicating is the bus already activated and configured by
+        * another substream
+        */
+       int                             active;
+       int                             configured;
+};
+
+#define to_mcbsp(priv) container_of((priv), struct omap_mcbsp_data, bus_id)
+
+static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
+
+/*
+ * Stream DMA parameters. DMA request line and port address are set runtime
+ * since they are different between OMAP1 and later OMAPs
+ */
+static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2] = {
+{
+       { .name         = "I2S PCM Stereo out", },
+       { .name         = "I2S PCM Stereo in", },
+},
+};
+
+#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
+static const int omap1_dma_reqs[][2] = {
+       { OMAP_DMA_MCBSP1_TX, OMAP_DMA_MCBSP1_RX },
+       { OMAP_DMA_MCBSP2_TX, OMAP_DMA_MCBSP2_RX },
+       { OMAP_DMA_MCBSP3_TX, OMAP_DMA_MCBSP3_RX },
+};
+static const unsigned long omap1_mcbsp_port[][2] = {
+       { OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1,
+         OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 },
+       { OMAP1510_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1,
+         OMAP1510_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 },
+       { OMAP1510_MCBSP3_BASE + OMAP_MCBSP_REG_DXR1,
+         OMAP1510_MCBSP3_BASE + OMAP_MCBSP_REG_DRR1 },
+};
+#else
+static const int omap1_dma_reqs[][2] = {};
+static const unsigned long omap1_mcbsp_port[][2] = {};
+#endif
+#if defined(CONFIG_ARCH_OMAP2420)
+static const int omap2420_dma_reqs[][2] = {
+       { OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX },
+       { OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX },
+};
+static const unsigned long omap2420_mcbsp_port[][2] = {
+       { OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1,
+         OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 },
+       { OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1,
+         OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 },
+};
+#else
+static const int omap2420_dma_reqs[][2] = {};
+static const unsigned long omap2420_mcbsp_port[][2] = {};
+#endif
+
+static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
+       int err = 0;
+
+       if (!cpu_dai->active)
+               err = omap_mcbsp_request(mcbsp_data->bus_id);
+
+       return err;
+}
+
+static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
+
+       if (!cpu_dai->active) {
+               omap_mcbsp_free(mcbsp_data->bus_id);
+               mcbsp_data->configured = 0;
+       }
+}
+
+static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
+       int err = 0;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               if (!mcbsp_data->active++)
+                       omap_mcbsp_start(mcbsp_data->bus_id);
+               break;
+
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               if (!--mcbsp_data->active)
+                       omap_mcbsp_stop(mcbsp_data->bus_id);
+               break;
+       default:
+               err = -EINVAL;
+       }
+
+       return err;
+}
+
+static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
+                                   struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
+       struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
+       int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
+       unsigned long port;
+
+       if (cpu_class_is_omap1()) {
+               dma = omap1_dma_reqs[bus_id][substream->stream];
+               port = omap1_mcbsp_port[bus_id][substream->stream];
+       } else if (cpu_is_omap2420()) {
+               dma = omap2420_dma_reqs[bus_id][substream->stream];
+               port = omap2420_mcbsp_port[bus_id][substream->stream];
+       } else {
+               /*
+                * TODO: Add support for 2430 and 3430
+                */
+               return -ENODEV;
+       }
+       omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma;
+       omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port;
+       cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream];
+
+       if (mcbsp_data->configured) {
+               /* McBSP already configured by another stream */
+               return 0;
+       }
+
+       switch (params_channels(params)) {
+       case 2:
+               /* Set 1 word per (McBPSP) frame and use dual-phase frames */
+               regs->rcr2      |= RFRLEN2(1 - 1) | RPHASE;
+               regs->rcr1      |= RFRLEN1(1 - 1);
+               regs->xcr2      |= XFRLEN2(1 - 1) | XPHASE;
+               regs->xcr1      |= XFRLEN1(1 - 1);
+               break;
+       default:
+               /* Unsupported number of channels */
+               return -EINVAL;
+       }
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               /* Set word lengths */
+               regs->rcr2      |= RWDLEN2(OMAP_MCBSP_WORD_16);
+               regs->rcr1      |= RWDLEN1(OMAP_MCBSP_WORD_16);
+               regs->xcr2      |= XWDLEN2(OMAP_MCBSP_WORD_16);
+               regs->xcr1      |= XWDLEN1(OMAP_MCBSP_WORD_16);
+               /* Set FS period and length in terms of bit clock periods */
+               regs->srgr2     |= FPER(16 * 2 - 1);
+               regs->srgr1     |= FWID(16 - 1);
+               break;
+       default:
+               /* Unsupported PCM format */
+               return -EINVAL;
+       }
+
+       omap_mcbsp_config(bus_id, &mcbsp_data->regs);
+       mcbsp_data->configured = 1;
+
+       return 0;
+}
+
+/*
+ * This must be called before _set_clkdiv and _set_sysclk since McBSP register
+ * cache is initialized here
+ */
+static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
+                                     unsigned int fmt)
+{
+       struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
+       struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
+
+       if (mcbsp_data->configured)
+               return 0;
+
+       memset(regs, 0, sizeof(*regs));
+       /* Generic McBSP register settings */
+       regs->spcr2     |= XINTM(3) | FREE;
+       regs->spcr1     |= RINTM(3);
+       regs->rcr2      |= RFIG;
+       regs->xcr2      |= XFIG;
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               /* 1-bit data delay */
+               regs->rcr2      |= RDATDLY(1);
+               regs->xcr2      |= XDATDLY(1);
+               break;
+       default:
+               /* Unsupported data format */
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+               /* McBSP master. Set FS and bit clocks as outputs */
+               regs->pcr0      |= FSXM | FSRM |
+                                  CLKXM | CLKRM;
+               /* Sample rate generator drives the FS */
+               regs->srgr2     |= FSGM;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFM:
+               /* McBSP slave */
+               break;
+       default:
+               /* Unsupported master/slave configuration */
+               return -EINVAL;
+       }
+
+       /* Set bit clock (CLKX/CLKR) and FS polarities */
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               /*
+                * Normal BCLK + FS.
+                * FS active low. TX data driven on falling edge of bit clock
+                * and RX data sampled on rising edge of bit clock.
+                */
+               regs->pcr0      |= FSXP | FSRP |
+                                  CLKXP | CLKRP;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               regs->pcr0      |= CLKXP | CLKRP;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               regs->pcr0      |= FSXP | FSRP;
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
+                                    int div_id, int div)
+{
+       struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
+       struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
+
+       if (div_id != OMAP_MCBSP_CLKGDV)
+               return -ENODEV;
+
+       regs->srgr1     |= CLKGDV(div - 1);
+
+       return 0;
+}
+
+static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
+                                      int clk_id)
+{
+       int sel_bit;
+       u16 reg;
+
+       if (cpu_class_is_omap1()) {
+               /* OMAP1's can use only external source clock */
+               if (unlikely(clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK))
+                       return -EINVAL;
+               else
+                       return 0;
+       }
+
+       switch (mcbsp_data->bus_id) {
+       case 0:
+               reg = OMAP2_CONTROL_DEVCONF0;
+               sel_bit = 2;
+               break;
+       case 1:
+               reg = OMAP2_CONTROL_DEVCONF0;
+               sel_bit = 6;
+               break;
+       /* TODO: Support for ports 3 - 5 in OMAP2430 and OMAP34xx */
+       default:
+               return -EINVAL;
+       }
+
+       if (cpu_class_is_omap2()) {
+               if (clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK) {
+                       omap_ctrl_writel(omap_ctrl_readl(reg) &
+                                        ~(1 << sel_bit), reg);
+               } else {
+                       omap_ctrl_writel(omap_ctrl_readl(reg) |
+                                        (1 << sel_bit), reg);
+               }
+       }
+
+       return 0;
+}
+
+static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
+                                        int clk_id, unsigned int freq,
+                                        int dir)
+{
+       struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
+       struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
+       int err = 0;
+
+       switch (clk_id) {
+       case OMAP_MCBSP_SYSCLK_CLK:
+               regs->srgr2     |= CLKSM;
+               break;
+       case OMAP_MCBSP_SYSCLK_CLKS_FCLK:
+       case OMAP_MCBSP_SYSCLK_CLKS_EXT:
+               err = omap_mcbsp_dai_set_clks_src(mcbsp_data, clk_id);
+               break;
+
+       case OMAP_MCBSP_SYSCLK_CLKX_EXT:
+               regs->srgr2     |= CLKSM;
+       case OMAP_MCBSP_SYSCLK_CLKR_EXT:
+               regs->pcr0      |= SCLKME;
+               break;
+       default:
+               err = -ENODEV;
+       }
+
+       return err;
+}
+
+struct snd_soc_cpu_dai omap_mcbsp_dai[NUM_LINKS] = {
+{
+       .name = "omap-mcbsp-dai",
+       .id = 0,
+       .type = SND_SOC_DAI_I2S,
+       .playback = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = OMAP_MCBSP_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .capture = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = OMAP_MCBSP_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .ops = {
+               .startup = omap_mcbsp_dai_startup,
+               .shutdown = omap_mcbsp_dai_shutdown,
+               .trigger = omap_mcbsp_dai_trigger,
+               .hw_params = omap_mcbsp_dai_hw_params,
+       },
+       .dai_ops = {
+               .set_fmt = omap_mcbsp_dai_set_dai_fmt,
+               .set_clkdiv = omap_mcbsp_dai_set_clkdiv,
+               .set_sysclk = omap_mcbsp_dai_set_dai_sysclk,
+       },
+       .private_data = &mcbsp_data[0].bus_id,
+},
+};
+EXPORT_SYMBOL_GPL(omap_mcbsp_dai);
+
+MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
+MODULE_DESCRIPTION("OMAP I2S SoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h
new file mode 100644 (file)
index 0000000..9965fd4
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * omap-mcbsp.h
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Contact: Jarkko Nikula <jarkko.nikula@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_I2S_H__
+#define __OMAP_I2S_H__
+
+/* Source clocks for McBSP sample rate generator */
+enum omap_mcbsp_clksrg_clk {
+       OMAP_MCBSP_SYSCLK_CLKS_FCLK,    /* Internal FCLK */
+       OMAP_MCBSP_SYSCLK_CLKS_EXT,     /* External CLKS pin */
+       OMAP_MCBSP_SYSCLK_CLK,          /* Internal ICLK */
+       OMAP_MCBSP_SYSCLK_CLKX_EXT,     /* External CLKX pin */
+       OMAP_MCBSP_SYSCLK_CLKR_EXT,     /* External CLKR pin */
+};
+
+/* McBSP dividers */
+enum omap_mcbsp_div {
+       OMAP_MCBSP_CLKGDV,              /* Sample rate generator divider */
+};
+
+/*
+ * REVISIT: Preparation for the ASoC v2. Let the number of available links to
+ * be same than number of McBSP ports found in OMAP(s) we are compiling for.
+ */
+#define NUM_LINKS      1
+
+extern struct snd_soc_cpu_dai omap_mcbsp_dai[NUM_LINKS];
+
+#endif
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
new file mode 100644 (file)
index 0000000..6237020
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+ * omap-pcm.c  --  ALSA PCM interface for the OMAP SoC
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Contact: Jarkko Nikula <jarkko.nikula@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/dma-mapping.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <asm/arch/dma.h>
+#include "omap-pcm.h"
+
+static const struct snd_pcm_hardware omap_pcm_hardware = {
+       .info                   = SNDRV_PCM_INFO_MMAP |
+                                 SNDRV_PCM_INFO_MMAP_VALID |
+                                 SNDRV_PCM_INFO_INTERLEAVED |
+                                 SNDRV_PCM_INFO_PAUSE |
+                                 SNDRV_PCM_INFO_RESUME,
+       .formats                = SNDRV_PCM_FMTBIT_S16_LE,
+       .period_bytes_min       = 32,
+       .period_bytes_max       = 64 * 1024,
+       .periods_min            = 2,
+       .periods_max            = 255,
+       .buffer_bytes_max       = 128 * 1024,
+};
+
+struct omap_runtime_data {
+       spinlock_t                      lock;
+       struct omap_pcm_dma_data        *dma_data;
+       int                             dma_ch;
+       int                             period_index;
+};
+
+static void omap_pcm_dma_irq(int ch, u16 stat, void *data)
+{
+       struct snd_pcm_substream *substream = data;
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct omap_runtime_data *prtd = runtime->private_data;
+       unsigned long flags;
+
+       if (cpu_is_omap1510()) {
+               /*
+                * OMAP1510 doesn't support DMA chaining so have to restart
+                * the transfer after all periods are transferred
+                */
+               spin_lock_irqsave(&prtd->lock, flags);
+               if (prtd->period_index >= 0) {
+                       if (++prtd->period_index == runtime->periods) {
+                               prtd->period_index = 0;
+                               omap_start_dma(prtd->dma_ch);
+                       }
+               }
+               spin_unlock_irqrestore(&prtd->lock, flags);
+       }
+
+       snd_pcm_period_elapsed(substream);
+}
+
+/* this may get called several times by oss emulation */
+static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
+                             struct snd_pcm_hw_params *params)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct omap_runtime_data *prtd = runtime->private_data;
+       struct omap_pcm_dma_data *dma_data = rtd->dai->cpu_dai->dma_data;
+       int err = 0;
+
+       if (!dma_data)
+               return -ENODEV;
+
+       snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+       runtime->dma_bytes = params_buffer_bytes(params);
+
+       if (prtd->dma_data)
+               return 0;
+       prtd->dma_data = dma_data;
+       err = omap_request_dma(dma_data->dma_req, dma_data->name,
+                              omap_pcm_dma_irq, substream, &prtd->dma_ch);
+       if (!cpu_is_omap1510()) {
+               /*
+                * Link channel with itself so DMA doesn't need any
+                * reprogramming while looping the buffer
+                */
+               omap_dma_link_lch(prtd->dma_ch, prtd->dma_ch);
+       }
+
+       return err;
+}
+
+static int omap_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct omap_runtime_data *prtd = runtime->private_data;
+
+       if (prtd->dma_data == NULL)
+               return 0;
+
+       if (!cpu_is_omap1510())
+               omap_dma_unlink_lch(prtd->dma_ch, prtd->dma_ch);
+       omap_free_dma(prtd->dma_ch);
+       prtd->dma_data = NULL;
+
+       snd_pcm_set_runtime_buffer(substream, NULL);
+
+       return 0;
+}
+
+static int omap_pcm_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct omap_runtime_data *prtd = runtime->private_data;
+       struct omap_pcm_dma_data *dma_data = prtd->dma_data;
+       struct omap_dma_channel_params dma_params;
+
+       memset(&dma_params, 0, sizeof(dma_params));
+       /*
+        * Note: Regardless of interface data formats supported by OMAP McBSP
+        * or EAC blocks, internal representation is always fixed 16-bit/sample
+        */
+       dma_params.data_type                    = OMAP_DMA_DATA_TYPE_S16;
+       dma_params.trigger                      = dma_data->dma_req;
+       dma_params.sync_mode                    = OMAP_DMA_SYNC_ELEMENT;
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               dma_params.src_amode            = OMAP_DMA_AMODE_POST_INC;
+               dma_params.dst_amode            = OMAP_DMA_AMODE_CONSTANT;
+               dma_params.src_or_dst_synch     = OMAP_DMA_DST_SYNC;
+               dma_params.src_start            = runtime->dma_addr;
+               dma_params.dst_start            = dma_data->port_addr;
+       } else {
+               dma_params.src_amode            = OMAP_DMA_AMODE_CONSTANT;
+               dma_params.dst_amode            = OMAP_DMA_AMODE_POST_INC;
+               dma_params.src_or_dst_synch     = OMAP_DMA_SRC_SYNC;
+               dma_params.src_start            = dma_data->port_addr;
+               dma_params.dst_start            = runtime->dma_addr;
+       }
+       /*
+        * Set DMA transfer frame size equal to ALSA period size and frame
+        * count as no. of ALSA periods. Then with DMA frame interrupt enabled,
+        * we can transfer the whole ALSA buffer with single DMA transfer but
+        * still can get an interrupt at each period bounary
+        */
+       dma_params.elem_count   = snd_pcm_lib_period_bytes(substream) / 2;
+       dma_params.frame_count  = runtime->periods;
+       omap_set_dma_params(prtd->dma_ch, &dma_params);
+
+       omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ);
+
+       return 0;
+}
+
+static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct omap_runtime_data *prtd = runtime->private_data;
+       int ret = 0;
+
+       spin_lock_irq(&prtd->lock);
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               prtd->period_index = 0;
+               omap_start_dma(prtd->dma_ch);
+               break;
+
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               prtd->period_index = -1;
+               omap_stop_dma(prtd->dma_ch);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       spin_unlock_irq(&prtd->lock);
+
+       return ret;
+}
+
+static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct omap_runtime_data *prtd = runtime->private_data;
+       dma_addr_t ptr;
+       snd_pcm_uframes_t offset;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               ptr = omap_get_dma_src_pos(prtd->dma_ch);
+       else
+               ptr = omap_get_dma_dst_pos(prtd->dma_ch);
+
+       offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
+       if (offset >= runtime->buffer_size)
+               offset = 0;
+
+       return offset;
+}
+
+static int omap_pcm_open(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct omap_runtime_data *prtd;
+       int ret;
+
+       snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware);
+
+       /* Ensure that buffer size is a multiple of period size */
+       ret = snd_pcm_hw_constraint_integer(runtime,
+                                           SNDRV_PCM_HW_PARAM_PERIODS);
+       if (ret < 0)
+               goto out;
+
+       prtd = kzalloc(sizeof(prtd), GFP_KERNEL);
+       if (prtd == NULL) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       spin_lock_init(&prtd->lock);
+       runtime->private_data = prtd;
+
+out:
+       return ret;
+}
+
+static int omap_pcm_close(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       kfree(runtime->private_data);
+       return 0;
+}
+
+static int omap_pcm_mmap(struct snd_pcm_substream *substream,
+       struct vm_area_struct *vma)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+
+       return dma_mmap_writecombine(substream->pcm->card->dev, vma,
+                                    runtime->dma_area,
+                                    runtime->dma_addr,
+                                    runtime->dma_bytes);
+}
+
+struct snd_pcm_ops omap_pcm_ops = {
+       .open           = omap_pcm_open,
+       .close          = omap_pcm_close,
+       .ioctl          = snd_pcm_lib_ioctl,
+       .hw_params      = omap_pcm_hw_params,
+       .hw_free        = omap_pcm_hw_free,
+       .prepare        = omap_pcm_prepare,
+       .trigger        = omap_pcm_trigger,
+       .pointer        = omap_pcm_pointer,
+       .mmap           = omap_pcm_mmap,
+};
+
+static u64 omap_pcm_dmamask = DMA_BIT_MASK(32);
+
+static int omap_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
+       int stream)
+{
+       struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+       struct snd_dma_buffer *buf = &substream->dma_buffer;
+       size_t size = omap_pcm_hardware.buffer_bytes_max;
+
+       buf->dev.type = SNDRV_DMA_TYPE_DEV;
+       buf->dev.dev = pcm->card->dev;
+       buf->private_data = NULL;
+       buf->area = dma_alloc_writecombine(pcm->card->dev, size,
+                                          &buf->addr, GFP_KERNEL);
+       if (!buf->area)
+               return -ENOMEM;
+
+       buf->bytes = size;
+       return 0;
+}
+
+static void omap_pcm_free_dma_buffers(struct snd_pcm *pcm)
+{
+       struct snd_pcm_substream *substream;
+       struct snd_dma_buffer *buf;
+       int stream;
+
+       for (stream = 0; stream < 2; stream++) {
+               substream = pcm->streams[stream].substream;
+               if (!substream)
+                       continue;
+
+               buf = &substream->dma_buffer;
+               if (!buf->area)
+                       continue;
+
+               dma_free_writecombine(pcm->card->dev, buf->bytes,
+                                     buf->area, buf->addr);
+               buf->area = NULL;
+       }
+}
+
+int omap_pcm_new(struct snd_card *card, struct snd_soc_codec_dai *dai,
+                struct snd_pcm *pcm)
+{
+       int ret = 0;
+
+       if (!card->dev->dma_mask)
+               card->dev->dma_mask = &omap_pcm_dmamask;
+       if (!card->dev->coherent_dma_mask)
+               card->dev->coherent_dma_mask = DMA_32BIT_MASK;
+
+       if (dai->playback.channels_min) {
+               ret = omap_pcm_preallocate_dma_buffer(pcm,
+                       SNDRV_PCM_STREAM_PLAYBACK);
+               if (ret)
+                       goto out;
+       }
+
+       if (dai->capture.channels_min) {
+               ret = omap_pcm_preallocate_dma_buffer(pcm,
+                       SNDRV_PCM_STREAM_CAPTURE);
+               if (ret)
+                       goto out;
+       }
+
+out:
+       return ret;
+}
+
+struct snd_soc_platform omap_soc_platform = {
+       .name           = "omap-pcm-audio",
+       .pcm_ops        = &omap_pcm_ops,
+       .pcm_new        = omap_pcm_new,
+       .pcm_free       = omap_pcm_free_dma_buffers,
+};
+EXPORT_SYMBOL_GPL(omap_soc_platform);
+
+MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
+MODULE_DESCRIPTION("OMAP PCM DMA module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h
new file mode 100644 (file)
index 0000000..e4369bd
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * omap-pcm.h
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * Contact: Jarkko Nikula <jarkko.nikula@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_PCM_H__
+#define __OMAP_PCM_H__
+
+struct omap_pcm_dma_data {
+       char            *name;          /* stream identifier */
+       int             dma_req;        /* DMA request line */
+       unsigned long   port_addr;      /* transmit/receive register */
+};
+
+extern struct snd_soc_platform omap_soc_platform;
+
+#endif